简介
Semaphore信号量计数器。和 CountDownLatch,CyclicBarrier 相似,是多线程合作的工具类,绝对于 join,wait,notify 办法应用起来简略高效。上面咱们次要看看它的用法吧!
实战
- 限流。限度线程的并发数。
比方在一个零碎中同时只能保障 5 个用户同时在线。
import java.util.concurrent.Semaphore;
/**
* @author:jiaolian
* @date:Created in 2021-03-04 11:13
* @description:Semaphore 限流
* @modified By:* 公众号: 叫练
*/
public class LimitCurrnet {public static void main(String[] args) throws InterruptedException {
// 定义 20 个线程,每次最多只能执行 5 个线程;
Semaphore semaphore = new Semaphore(5);
for (int i=0; i<20; i++) {new Thread(()->{
try {
// 获取凭证
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"登录胜利");
Thread.sleep(2000);
// 开释凭证
semaphore.release();
System.out.println(Thread.currentThread().getName()+"用户退出");
} catch (InterruptedException e) {e.printStackTrace();
}
}).start();}
}
}
如上代码所示:咱们定义了 20 个用户同时拜访零碎,Semaphore 参数是 5,示意同时只能有 5 个用户能够获取凭证,其余用户必须期待直到有在线用户退出。调用 semaphore.acquire()示意获取凭证,此时凭证数会减一,调用 semaphore.release()示意开释凭证,凭证数会加一,如果零碎中有期待的用户,操作此办法会告诉期待的一个用户获取凭证胜利,执行登录操作。最初打印 局部后果 如下:证实零碎最多能放弃 5 个用户同时在线。
留神:下面举出的这个案例,出个思考题:线程池是否能够实现呢?
- 模仿 CyclicBarrier,CountDownLatch 重用!
Semaphore 能够轻松实现 CountDownLatch 计数器,CyclicBarrier回环屏障,还记得 CountDownLatch 用法么?它是个计数器,能够帮咱们统计线程执行工夫,罕用来测试多线程高并发执行接口效率,咱们上面用 Semaphore 模仿多线程主线程期待子线程执行结束再返回。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author:jiaolian
* @date:Created in 2021-03-01 21:04
* @description:信号量测试
* @modified By:* 公众号: 叫练
*/
public class SemaphoreTest {
// 定义线程数量;
private static final int THREAD_COUNT = 2;
// 初始化信号量为 0,默认是非偏心锁
private static Semaphore semaphore = new Semaphore(0,false);
private static ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
public static void main(String[] args) throws InterruptedException {for (int i=0; i<THREAD_COUNT; i++) {executorService.submit(()->{
try {Thread.sleep(2000);
} catch (InterruptedException e) {e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行");
semaphore.release();});
}
// 获取 2 个信号量
semaphore.acquire(2);
System.out.println("主线程执行结束");
executorService.shutdown();}
}
如上代码所示:咱们定义了 Semaphore 初始化信号量为 0,默认是非偏心锁,在主线程中用线程池提交 2 个线程,主线程调用 semaphore.acquire(2)示意须要获取两个信号量,但此时初始化信号量为 0,此时 AQS 中的 state 会是 0 -2=-2,state 值小于 0,所以主线程执行这句话会阻塞将其退出 AQS 同步队列,线程池两个线程期待 2 秒后会调用 semaphore.release()开释 2 个信号量,此时 AQS 中的 state 会自增到 0,会告诉主线程退出期待持续往下执行。执行后果如下图所示。
有没有发现 Semaphore 用法能够模仿 CountDownLatch,另外Semaphore 通过调用 acquire,release 办法,还能够实现 CyclicBarrier 性能!咱们不举例了。
实现原理
- 相同点:实质上都是计数器,底层是依赖 AQS 操作 state 实现。
- 异同点:CountDownLatch是共享锁实现,CyclicBarrier是独占锁实现,CountDownLatch通过调用 countDown 递加计数器只能应用一次,而 CyclicBarrier 通过调用 await 递加计数器能够达到“回环”反复的成果。Semaphore 也是共享锁实现,通过调用 release 计数器是递增的,通过设置信号量能够实现 CyclicBarrier,CountDownLatch 性能。
总结
明天咱们介绍了 Semaphore,整理出来心愿能对你有帮忙,写的比不全,同时还有许多须要修改的中央,心愿亲们加以斧正和点评,喜爱的请点赞加关注哦。 点关注,不迷路,我是【叫练 】 公众号 ,微信号【jiaolian123abc】 边叫边练。