关于Semaphore的使用介绍

1.什么是Semaphore

Semaphore是一个计数信号量,通常用于限制对某些资源访问的线程数量,Semaphore管理一系列许可证。举个栗子:

  • 假如我们要去游泳池游泳,泳池一共有6条泳道,每条泳道只能有1个人在上面使用。每个人去游泳之前要先 acquire() 一下获取许可证,如果有空闲泳道就可以去游泳;如果没有空闲泳道,就只能阻塞等待。游完泳之后,再 release() 一下释放许可证,释放出该泳道的使用权,确保下一个人 acquire() 的时候可以获取可用泳道,继续游泳。如果泳道上都有人了,再有人过来游泳,就需要等待其他人。
  • 这个泳道的数量,我们是可以自行设定的。这里的泳池就是共享资源,而泳道的数量就是可访问的线程数量,游泳者就是线程。

2.Semaphore的简单使用

public class SemaphoreTest {

    public static void main(String[] args) {
        //创建一个可缓存的线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //信号量
        Semaphore semaphore = new Semaphore(6);
        System.out.println("初始化: 当前有" + semaphore.availablePermits() + "个泳道可用");
        //创建10个任务(相当于10个游泳者)
        for (int i = 0; i < 10; i++) {
            //记录第几个任务(相当于第几个游泳者)
            final int No = i;
            executor.execute(() -> {
                try {
                    semaphore.acquire();    //获取许可
                    System.out.println(Thread.currentThread().getName() + "游泳者" + No + "获取了许可(获取了泳道)," + "还剩"
                            + semaphore.availablePermits() + "个泳道可用~");
                    //执行耗时操作(相当于正在游泳)
                    Thread.sleep(1000);
                    semaphore.release();    //释放许可
                    System.out.println(Thread.currentThread().getName() + "游泳者" + No + "释放了许可(离开了泳道)," + "还剩"
                            + semaphore.availablePermits() + "个泳道可用~");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        //关闭线程池
        executor.shutdown();
    }
}

打印结果之一,每次运行都可能不一样:

初始化: 当前有6个泳道可用
pool-1-thread-1游泳者0获取了许可(获取了泳道),还剩5个泳道可用~
pool-1-thread-2游泳者1获取了许可(获取了泳道),还剩4个泳道可用~
pool-1-thread-3游泳者2获取了许可(获取了泳道),还剩3个泳道可用~
pool-1-thread-4游泳者3获取了许可(获取了泳道),还剩2个泳道可用~
pool-1-thread-5游泳者4获取了许可(获取了泳道),还剩1个泳道可用~
pool-1-thread-6游泳者5获取了许可(获取了泳道),还剩0个泳道可用~
pool-1-thread-7游泳者6获取了许可(获取了泳道),还剩0个泳道可用~
pool-1-thread-1游泳者0释放了许可(离开了泳道),还剩0个泳道可用~
pool-1-thread-8游泳者7获取了许可(获取了泳道),还剩0个泳道可用~
pool-1-thread-5游泳者4释放了许可(离开了泳道),还剩0个泳道可用~
pool-1-thread-9游泳者8获取了许可(获取了泳道),还剩0个泳道可用~
pool-1-thread-4游泳者3释放了许可(离开了泳道),还剩0个泳道可用~
pool-1-thread-3游泳者2释放了许可(离开了泳道),还剩1个泳道可用~
pool-1-thread-2游泳者1释放了许可(离开了泳道),还剩1个泳道可用~
pool-1-thread-10游泳者9获取了许可(获取了泳道),还剩0个泳道可用~
pool-1-thread-6游泳者5释放了许可(离开了泳道),还剩2个泳道可用~
pool-1-thread-7游泳者6释放了许可(离开了泳道),还剩3个泳道可用~
pool-1-thread-10游泳者9释放了许可(离开了泳道),还剩4个泳道可用~
pool-1-thread-9游泳者8释放了许可(离开了泳道),还剩5个泳道可用~
pool-1-thread-8游泳者7释放了许可(离开了泳道),还剩6个泳道可用~

看了上面的结果,你是不是觉得获取泳道使用权或者释放泳道使用权之后,剩下可用泳道的数量是不是不对呀!其实是没错的,只是因为线程运行太快,acquire()方法或者release()方法在打印语句执行之前,就已经执行了,所以看起来结果才好像不大对。

简单介绍就到这里啦,更多介绍请点击下面链接~

戳我详细了解Semaphore

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐