多线程基础(九)信号量Semaphore——[ˈseməfɔːr]

1. Semaphore----[ˈseməfɔːr]
信号量可以理解为限流算法令牌算法里的令牌池,他是对锁的扩展,无论synchronized还是Lock一次只允许一个线程访问资源,而Semaphore内部维护了一个信号量计数器,当线程访问资源时将计数器减一,访问完毕后计数器加一,当计数器减到0时再有线程来获取锁将会等待,当有一个线程执行完毕释放锁后计数器加一不为0,此时等待的线程可以获取锁并把计数器减一。
其构造函数:
public Semaphore(int permits)
public Semaphore(int permits, boolean fair)
permits:信号计数器初始值
fair:是否公平锁
其常用方法:
acquire()
tryAcquire()
tryAcquire(long timeout, TimeUnit unit)
acquireUninterruptibly():不响应中断
release()
用法与Lock的相关用法是一样的,这里不细述了,可以看多线程基础(四)Lock

2. 示例
控制最多同时只能有两个线程拿到锁

public class Test05 {
    // [ˈseməfɔːr] 信号量
    private static Semaphore semaphore = new Semaphore(2);
    private static int coreSize = 10;
    private static long timeOut = 10;
    private static LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
    private static TimeUnit timeUnit = TimeUnit.SECONDS;
    private static AtomicInteger index = new AtomicInteger(0);

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, coreSize, timeOut, timeUnit, queue);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 8; i++) {
            executor.submit(() -> {
                try {
                    semaphore.acquire();
                    TimeUnit.SECONDS.sleep(1);
                    int name = index.incrementAndGet();
                    System.out.println("第" + name + "个线程执行完毕:" + (System.currentTimeMillis() - start) / 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            });
        }
        executor.shutdown();
    }
}

执行结果:

第1个线程执行完毕:1
第2个线程执行完毕:1
第3个线程执行完毕:2
第4个线程执行完毕:2
第5个线程执行完毕:3
第6个线程执行完毕:3
第7个线程执行完毕:4
第8个线程执行完毕:4
上一篇:四.并发编程 (线程信号量)


下一篇:SEMer必看!一张图学会如何用四象分析法做好数据分析-SEM学习