JDK1.8 信号量(Semaphore)的基本使用

Posted zhujm320

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8 信号量(Semaphore)的基本使用相关的知识,希望对你有一定的参考价值。

介绍

信号量支持多线程同时并发,但是同时并发线程数是确定的,起到了限流的作用。比如: 临界资源的数量是5个,那么则可以同时支持5个线程进入临界资源,待进入临界资源的线程退出后,其他线程才能进入来,也就是说当前占用临界资源的线程小于5个,其他线程才能进来。以停车场的车位为例: 停车场有5个车位,如果都停满了车,那么其他车就无法进来;反之,其他车可以进入停车场,直接到车位停满。

使用

初始化信号量

public Semaphore(int permits) {   	
	sync = new NonfairSync(permits);
}

permits表示信号量个数(即临界资源个数),默认采用非公平同步策略。

尝试获取信号量

public boolean tryAcquire() {
        return sync.nonfairTryAcquireShared(1) >= 0;
}

判断是否有可用的信号量,非阻塞调用,如果有,直接返回true,反之返回false

尝试在指定时间内获取信号量

public boolean tryAcquire(long timeout, TimeUnit unit)    
	throws InterruptedException {    
	return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

在指定时间内尝试获取信号量,阻塞调用(在指定时间内),如果有,直接返回true,反之返回false

timeout 超时时间

unit 超时时间单位

获取信号量

public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
 }

直接获取信号量,阻塞调用,如果有可用信号量,直接返回,信号量个数减一;如果可用信号量为0,则阻塞

public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
 }

同时获取几个信号量,阻塞调用,如果有足够可用信号量,直接返回,信号量个数减permits;如果可用信号量小于permits,则阻塞

释放新号量

public void release() {
        sync.releaseShared(1);
}

释放一个信号量,信号量个数加1,如果有线程阻塞在acquire()函数,那么将被唤醒,并获取到信号量,并往下执行。

public void release(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
}

释放permits个信号量(表示释放临界资源个数),信号量个数加permits

清空信号量

public int drainPermits() {
        return sync.drainPermits();
}

将信号量个数清零,此时无可用的信号量

获取等待线程个数

public final int getQueueLength() {
        return sync.getQueueLength();
}

该方法可以判断有多少线程阻塞在获取信号量函数上(即有多少线程调用了acquire())

测试例子

代码:

package sample;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {



    public static void main(String[] args) {

        Semaphore semaphore=new Semaphore(24);
//        int count = semaphore.availablePermits();
//        System.out.println("可用信号量 count1: " + count);
//        //增加20个信号量
//        semaphore.release(20);
        int count = semaphore.availablePermits();
        //此时信号量个数为24个, 可以支持同时跑24个线程
        System.out.println("可用信号量 count2: " + count);
        for (int i = 0; i < 200; i ++){
            new Thread(()->{
                try {
                    semaphore.acquire();
                    System.out.println("" + Thread.currentThread().getName() + " 进入" + " 时间: " + System.currentTimeMillis());
                    Thread.sleep(200);
                    System.out.println("" + Thread.currentThread().getName() + " 退出" + " 时间: " + System.currentTimeMillis());
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "线程"+i).start();
        }
        //延迟一下等待获取信号量的线程全部进入等待队列
        try{
            Thread.sleep(10);
        }catch (Exception e){
            e.printStackTrace();
        }
        int waitT = semaphore.getQueueLength();
        System.out.println("等待线程个数: " + waitT + " 时间: " + System.currentTimeMillis());
    }


}

输出结果:

可用信号量 count2: 24
线程0 进入 时间: 1621138709578
线程3 进入 时间: 1621138709578
线程2 进入 时间: 1621138709578
线程1 进入 时间: 1621138709578
线程4 进入 时间: 1621138709578
线程5 进入 时间: 1621138709578
线程6 进入 时间: 1621138709578
线程7 进入 时间: 1621138709578
线程8 进入 时间: 1621138709578
线程9 进入 时间: 1621138709578
线程19 进入 时间: 1621138709578
线程10 进入 时间: 1621138709578
线程12 进入 时间: 1621138709578
线程17 进入 时间: 1621138709578
线程11 进入 时间: 1621138709578
线程21 进入 时间: 1621138709578
线程18 进入 时间: 1621138709578
线程20 进入 时间: 1621138709578
线程13 进入 时间: 1621138709578
线程22 进入 时间: 1621138709578
线程16 进入 时间: 1621138709578
线程15 进入 时间: 1621138709578
线程14 进入 时间: 1621138709578
线程23 进入 时间: 1621138709578
等待线程个数: 176 时间: 1621138709610
线程0 退出 时间: 1621138709783
线程17 退出 时间: 1621138709783
线程7 退出 时间: 1621138709783
线程24 进入 时间: 1621138709783
线程16 退出 时间: 1621138709783
线程15 退出 时间: 1621138709783
线程12 退出 时间: 1621138709783
线程21 退出 时间: 1621138709783
线程29 进入 时间: 1621138709783
线程22 退出 时间: 1621138709783
线程31 进入 时间: 1621138709783
线程11 退出 时间: 1621138709783
线程4 退出 时间: 1621138709783
线程32 进入 时间: 1621138709783
线程9 退出 时间: 1621138709783
线程2 退出 时间: 1621138709783
线程6 退出 时间: 1621138709783
线程1 退出 时间: 1621138709783
线程10 退出 时间: 1621138709783
线程3 退出 时间: 1621138709783
线程38 进入 时间: 1621138709783
线程5 退出 时间: 1621138709783
线程39 进入 时间: 1621138709783
线程37 进入 时间: 1621138709783
线程36 进入 时间: 1621138709783
线程35 进入 时间: 1621138709783
线程34 进入 时间: 1621138709783
线程33 进入 时间: 1621138709783
线程30 进入 时间: 1621138709783
线程28 进入 时间: 1621138709783
线程27 进入 时间: 1621138709783
线程26 进入 时间: 1621138709783
线程25 进入 时间: 1621138709783
线程8 退出 时间: 1621138709783
线程14 退出 时间: 1621138709783
线程18 退出 时间: 1621138709783
线程20 退出 时间: 1621138709783
线程23 退出 时间: 1621138709783
线程44 进入 时间: 1621138709783
线程19 退出 时间: 1621138709783
线程13 退出 时间: 1621138709783
线程46 进入 时间: 1621138709783
线程45 进入 时间: 1621138709783
线程43 进入 时间: 1621138709783
线程42 进入 时间: 1621138709783
线程41 进入 时间: 1621138709783
线程40 进入 时间: 1621138709783
线程47 进入 时间: 1621138709783
线程31 退出 时间: 1621138709986
线程43 退出 时间: 1621138709986
线程48 进入 时间: 1621138709986
线程38 退出 时间: 1621138709986
线程37 退出 时间: 1621138709986
线程47 退出 时间: 1621138709986
线程45 退出 时间: 1621138709986
线程46 退出 时间: 1621138709986
线程40 退出 时间: 1621138709986
线程41 退出 时间: 1621138709986
线程42 退出 时间: 1621138709986
线程27 退出 时间: 1621138709986
线程35 退出 时间: 1621138709986
线程30 退出 时间: 1621138709986
线程28 退出 时间: 1621138709986
线程33 退出 时间: 1621138709986
线程62 进入 时间: 1621138709986
线程39 退出 时间: 1621138709986
线程36 退出 时间: 1621138709986
线程29 退出 时间: 1621138709986
线程64 进入 时间: 1621138709986
线程32 退出 时间: 1621138709986
线程24 退出 时间: 1621138709986
线程34 退出 时间: 1621138709986
线程67 进入 时间: 1621138709986
线程66 进入 时间: 1621138709986
线程65 进入 时间: 1621138709986
线程63 进入 时间: 1621138709986
线程61 进入 时间: 1621138709986
线程60 进入 时间: 1621138709986
线程59 进入 时间: 1621138709986
线程58 进入 时间: 1621138709986
线程57 进入 时间: 1621138709986
线程56 进入 时间: 1621138709986
线程55 进入 时间: 1621138709986
线程54 进入 时间: 1621138709986
线程53 进入 时间: 1621138709986
线程52 进入 时间: 1621138709986
线程51 进入 时间: 1621138709986
线程50 进入 时间: 1621138709986
线程49 进入 时间: 1621138709986
线程44 退出 时间: 1621138709986
线程25 退出 时间: 1621138709986
线程69 进入 时间: 1621138709986
线程26 退出 时间: 1621138709986
线程70 进入 时间: 1621138709986
线程68 进入 时间: 1621138709986
线程71 进入 时间: 1621138709986
线程68 退出 时间: 1621138710189
线程55 退出 时间: 1621138710189
线程58 退出 时间: 1621138710189
线程73 进入 时间: 1621138710189
线程50 退出 时间: 1621138710189
线程49 退出 时间: 1621138710189
线程75 进入 时间: 1621138710189
线程74 进入 时间: 1621138710189
线程67 退出 时间: 1621138710189
线程64 退出 时间: 1621138710189
线程62 退出 时间: 1621138710189
线程56 退出 时间: 1621138710189
线程61 退出 时间: 1621138710189
线程63 退出 时间: 1621138710189
线程57 退出 时间: 1621138710189
线程65 退出 时间: 1621138710189
线程83 进入 时间: 1621138710189
线程66 退出 时间: 1621138710189
线程52 退出 时间: 1621138710189
线程48 退出 时间: 1621138710189
线程87 进入 时间: 1621138710189
线程59 退出 时间: 1621138710189
线程60 退出 时间: 1621138710189
线程51 退出 时间: 1621138710189
线程89 进入 时间: 1621138710189
线程53 退出 时间: 1621138710189
线程71 退出 时间: 1621138710189
线程72 进入 时间: 1621138710189
线程92 进入 时间: 1621138710189
线程69 退出 时间: 1621138710189
线程70 退出 时间: 1621138710189
线程54 退出 时间: 1621138710189
线程94 进入 时间: 1621138710189
线程93 进入 时间: 1621138710189
线程91 进入 时间: 1621138710189
线程90 进入 时间: 1621138710189
线程88 进入 时间: 1621138710189
线程86 进入 时间: 1621138710189
线程85 进入 时间: 1621138710189
线程84 进入 时间: 1621138710189
线程82 进入 时间: 1621138710189
线程81 进入 时间: 1621138710189
线程80 进入 时间: 1621138710189
线程79 进入 时间: 1621138710189
线程78 进入 时间: 1621138710189
线程77 进入 时间: 1621138710189
线程76 进入 时间: 1621138710189
线程95 进入 时间: 1621138710189
线程79 退出 时间: 1621138710392
线程88 退出 时间: 1621138710392
线程82 退出 时间: 1621138710392
线程97 进入 时间: 1621138710392
线程94 退出 时间: 1621138710392
线程73 退出 时间: 1621138710392
线程99 进入 时间: 1621138710392
线程96 进入 时间: 1621138710392
线程91 退出 时间: 1621138710392
线程74 退出 时间: 1621138710392
线程101 进入 时间: 1621138710392
线程92 退出 时间: 1621138710392
线程81 退出 时间: 1621138710392
线程85 退出 时间: 1621138710392
线程86 退出 时间: 1621138710392
线程80 退出 时间: 1621138710392
线程107 进入 时间: 1621138710392
线程72 退出 时间: 1621138710392
线程83 退出 时间: 1621138710392
线程108 进入 时间: 1621138710392
线程89 退出 时间: 1621138710392
线程110 进入 时间: 1621138710392
线程76 退出 时间: 1621138710392
线程111 进入 时间: 1621138710392
线程77 退出 时间: 1621138710392
线程84 退出 时间: 1621138710392
线程113 进入 时间: 1621138710392
线程90 退出 时间: 1621138710392
线程114 进入 时间: 1621138710394
线程78 退出 时间: 1621138710392
线程95 退出 时间: 1621138710392
线程115 进入 时间: 1621138710394
线程112 进入 时间: 1621138710392
线程109 进入 时间: 1621138710392
线程106 进入 时间: 1621138710392
线程105 进入 时间: 1621138710392
线程104 进入 时间: 1621138710392
线程103 进入 时间: 1621138710392
线程102 进入 时间: 1621138710392
线程100 进入 时间: 1621138710392
线程98 进入 时间: 1621138710392
线程75 退出 时间: 1621138710392
线程87 退出 时间: 1621138710392
线程118 进入 时间: 1621138710395
线程93 退出 时间: 1621138710392
线程117 进入 时间: 1621138710395
线程119 进入 时间: 1621138710395
线程116 进入 时间: 1621138710394
线程104 退出 时间: 1621138710604
线程98 退出 时间: 1621138710604
线程120 进入 时间: 1621138710604
线程97 退出 时间: 1621138710604
线程115 退出 时间: 1621138710604
线程109 退出 时间: 1621138710604
线程110 退出 时间: 1621138710604
线程103 退出 时间: 1621138710604
线程96 退出 时间: 1621138710604
线程126 进入 时间: 1621138710604
线程99 退出 时间: 1621138710604
线程128 进入 时间: 1621138710604
线程112 退出 时间: 1621138710604
线程111 退出 时间: 1621138710604
线程101 退出 时间: 1621138710604
线程116 退出 时间: 1621138710604
线程108 退出 时间: 1621138710604
线程132 进入 时间: 1621138710604
线程107 退出 时间: 1621138710604
线程100 退出 时间: 1621138710604
线程106 退出 时间: 1621138710604
线程118 退出 时间: 1621138710604
线程113 退出 时间: 1621138710604
线程114 退出 时间: 1621138710604
线程105 退出 时间: 1621138710604
线程117 退出 时间: 1621138710604
线程119 退出 时间: 1621138710604
线程102 退出 时间: 1621138710604
线程142 进入 时间: 1621138710604
线程141 进入 时间: 1621138710604
线程140 进入 时间: 1621138710604
线程139 进入 时间: 1621138710604
线程138 进入 时间: 1621138710604
线程137 进入 时间: 1621138710604
线程136 进入 时间: 1621138710604
线程135 进入 时间: 1621138710604
线程134 进入 时间: 1621138710604
线程133 进入 时间: 1621138710604
线程131 进入 时间: 1621138710604
线程130 进入 时间: 1621138710604
线程129 进入 时间: 1621138710604
线程127 进入 时间: 1621138710604
线程125 进入 时间: 1621138710604
线程124 进入 时间: 1621138710604
线程123 进入 时间: 1621138710604
线程122 进入 时间: 1621138710604
线程121 进入 时间: 1621138710604
线程143 进入 时间: 1621138710604
线程140 退出 时间: 1621138710809
线程124 退出 时间: 1621138710809
线程144 进入 时间: 1621138710809
线程123 退出 时间: 1621138710809
线程138 退出 时间: 1621138710809
线程127 退出 时间: 1621138710809
线程121 退出 时间: 1621138710809
线程149 进入 时间: 1621138710809
线程122 退出 时间: 1621138710809
线程125 退出 时间: 1621138710809
线程150 进入 时间: 1621138710809
线程133 退出 时间: 1621138710809
线程152 进入 时间: 1621138710809
线程143 退出 时间: 1621138710809
线程131 退出 时间: 1621138710809
线程153 进入 时间: 1621138710809
线程134 退出 时间: 1621138710809
线程137 退出 时间: 1621138710809
线程130 退出 时间: 1621138710809
线程156 进入 时间: 1621138710809
线程129 退出 时间: 1621138710809
线程126 退出 时间: 1621138710809
线程141 退出 时间: 1621138710809
线程135 退出 时间: 1621138710809
线程142 退出 时间: 1621138710809
线程132 退出 时间: 1621138710809
线程120 退出 时间: 1621138710809
线程136 退出 时间: 1621138710809
线程139 退出 时间: 1621138710809
线程128 退出 时间: 1621138710809
线程166 进入 时间: 1621138710809
线程165 进入 时间: 1621138710809
线程164 进入 时间: 1621138710809
线程163 进入 时间: 1621138710809
线程162 进入 时间: 1621138710809
线程161 进入 时间: 1621138710809
线程160 进入 时间: 1621138710809
线程159 进入 时间: 1621138710809
线程158 进入 时间: 1621138710809
线程157 进入 时间: 1621138710809
线程155 进入 时间: 1621138710809
线程154 进入 时间: 1621138710809
线程151 进入 时间: 1621138710809
线程148 进入 时间: 1621138710809
线程147 进入 时间: 1621138710809
线程146 进入 时间: 1621138710809
线程145 进入 时间: 1621138710809
线程167 进入 时间: 1621138710809
线程144 退出 时间: 1621138711036
线程167 退出 时间: 1621138711036
线程151 退出 时间: 1621138711036
线程170 进入 时间: 1621138711036
线程145 退出 时间: 1621138711036
线程159 退出 时间: 1621138711036
线程147 退出 时间: 1621138711036
线程172 进入 时间: 1621138711036
线程154 退出 时间: 1621138711036
线程148 退出 时间: 1621138711036
线程161 退出 时间: 1621138711036
线程175 进入 时间: 1621138711036
线程162 退出 时间: 1621138711036
线程160 退出 时间: 1621138711036
线程149 退出 时间: 1621138711036
线程178 进入 时间: 1621138711036
线程158 退出 时间: 1621138711036
线程157 退出 时间: 1621138711036
线程163 退出 时间: 1621138711036
线程153 退出 时间: 1621138711036
线程165 退出 时间: 1621138711036
线程166 退出 时间: 1621138711036
线程184 进入 时间: 1621138711036
线程150 退出 时间: 1621138711036
线程186 进入 时间: 1621138711036
线程152 退出 时间: 1621138711036
线程164 退出 时间: 1621138711036
线程156 退出 时间: 1621138711036
线程188 进入 时间: 1621138711036
线程189 进入 时间: 1621138711036
线程187 进入 时间: 1621138711036
线程185 进入 时间: 1621138711036
线程183 进入 时间: 1621138711036
线程182 进入 时间: 1621138711036
线程181 进入 时间: 1621138711036
线程180 进入 时间: 1621138711036
线程179 进入 时间: 1621138711036
线程177 进入 时间: 1621138711036
线程176 进入 时间: 1621138711036
线程174 进入 时间: 1621138711036
线程173 进入 时间: 1621138711036
线程171 进入 时间: 1621138711036
线程169 进入 时间: 1621138711036
线程146 退出 时间: 1621138711036
线程168 进入 时间: 1621138711036
线程155 退出 时间: 1621138711036
线程191 进入 时间: 1621138711036
线程190 进入 时间: 1621138711036
线程191 退出 时间: 1621138711241
线程170 退出 时间: 1621138711241
线程189 退出 时间: 1621138711241
线程172 退出 时间: 1621138711241
线程187 退出 时间: 1621138711241
线程195 进入 时间: 1621138711241
线程196 进入 时间: 1621138711241
线程188 退出 时间: 1621138711241
线程175 退出 时间: 1621138711241
线程182 退出 时间: 1621138711241
线程178 退出 时间: 1621138711241
线程184 退出 时间: 1621138711241
线程185 退出 时间: 1621138711241
线程177 退出 时间: 1621138711241
线程190 退出 时间: 1621138711241
线程183 退出 时间: 1621138711241
线程180 退出 时间: 1621138711241
线程186 退出 时间: 1621138711241
线程181 退出 时间: 1621138711241
线程176 退出 时间: 1621138711241
线程171 退出 时间: 1621138711241
线程168 退出 时间: 1621138711241
线程173 退出 时间: 1621138711241
线程169 退出 时间: 1621138711241
线程179 退出 时间: 1621138711241
线程174 退出 时间: 1621138711241
线程199 进入 时间: 1621138711241
线程198 进入 时间: 1621138711241
线程197 进入 时间: 1621138711241
线程194 进入 时间: 1621138711241
线程193 进入 时间: 1621138711241
线程192 进入 时间: 1621138711241
线程194 退出 时间: 1621138711444
线程196 退出 时间: 1621138711444
线程198 退出 时间: 1621138711444
线程197 退出 时间: 1621138711444
线程192 退出 时间: 1621138711444
线程195 退出 时间: 1621138711444
线程199 退出 时间: 1621138711444
线程193 退出 时间: 1621138711444

Process finished with exit code 0

 从测试结果看,支持同时并发24个线程,待获取到信号量的线程释放信号量后,其他线程依次获取到信号量并执行。

 

 

 

 

 

 

以上是关于JDK1.8 信号量(Semaphore)的基本使用的主要内容,如果未能解决你的问题,请参考以下文章

用synchronized实现Semaphore

用synchronized实现Semaphore

Java中的并发工具类:Semaphore基本理解和底层实现

多线程之Semaphore详解

Operating System: Semaphore

后端程序员之路 42Semaphore