Java多线程信号量同步类CountDownLatch与Semaphore

  信号量同步是指在不同线程之间,通过传递同步信号量来协调线程执行的先后次序。CountDownLatch是基于时间维度的Semaphore则是基于信号维度的。

1:基于执行时间的同步类CountDownLatch

  例如现有3台服务器,需编写一个获取各个服务器状态的接口,准备开三个子线程每个线程获取一台服务器状态后统一返回三台服务器状态。主线程内定义计数器为3的CountDownLatch实例,各个子线程添加CountDownLatch实例引用,子线程执行完后对CountDownLatch进行countDown。主线程调用CountDownLatch实例的await方法等待所有子线程执行完后返回结果。不考虑异常情况的代码示例如下。

public class Main {    public static void main(String[] args) throws InterruptedException {        CountDownLatch count = new CountDownLatch(3);        Thread getServer1Status = new GetDataStatusThread("服务器1", count);        Thread getServer2Status = new GetDataStatusThread("服务器2", count);        Thread getServer3Status = new GetDataStatusThread("服务器3", count);        getServer1Status.start();        getServer2Status.start();        getServer3Status.start();        //await 使当前线程等待直至CountDownLatch的计数为0,除非线程中断        //count.await();        //await(long timeout, TimeUnit unit) 使当前线程等待直至CountDownLatch的计数为0,除非线程中断或经过指定的等候时间        count.await(10,TimeUnit.SECONDS);        System.out.println("所有服务器状态获取完成");    }}class GetDataStatusThread extends  Thread {    private final CountDownLatch count;    public GetDataStatusThread(String threadName, CountDownLatch count) {        this.setName(threadName);        this.count = count;    }    @Override    public void run() {        System.out.println("获取" + this.getName() + "状态成功");        //递减CountDownLatch的计数,如果计数达到零,则释放所有等待的线程        count.countDown();    }}

   注意:CountDownLatchawait方法建议使用带超时间的。不使用带超时时间await的线程若计数器初始值设置的值达不到countDown(递减计数器计数)次数则该线程会一直等待至计数为0,除非线程中断

(例如子线程执行过程中出现异常执行不到countDown方法,顺便补充若子线程会抛出异常且该异常没有被主线程捕获到可通过线程方法setUncaughtExceptionHandler()捕获)。

2:基于空闲信号的同步类Semaphore

Semaphore可看作一个管理“许可证”的池,创建Semaphore实例时指定许可证数量,所有包含Semaphore实例引用的线程运行时通过acquire方法获取许可证,运行完成后通过release方法释放许可证。获取不到许可证等线程直到获取到空闲许可证才会执行。如下代码所示:某景区只有两个买票窗口(许可池大小)所有游客排队进行买票,准备买票的游客通过acquire占据当前窗口买票完成准备离开通过release方法表示当前窗口已空闲。

1public class Window { 2 3 public static void main(String[] args) { 4 Semaphore semaphore = new Semaphore(2); 5 6 for (int i = 1; i <= 6; i++) { 7 new ByTicketThread("客户" + i, semaphore).start(); 8 } 9 } 10 11} 12 13class ByTicketThread extends Thread { 14 15 private final Semaphore semaphore; 16 17 public ByTicketThread(String threadName, Semaphore semaphore) { 18 this.setName(threadName); 19 this.semaphore = semaphore; 20 } 21 22 @Override 23 public void run() { 24 try { 25 semaphore.acquire(); 26 System.out.println(this.getName() + "正在买票。"); 27 Thread.sleep(1000); 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } finally { 31 semaphore.release(); 32 System.out.println(this.getName() + "买票完成。"); 33 } 34 35 } 36}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

一篇文章带你了解JavaScript日期

日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用

Java多线程信号量同步类CountDownLatch与Semaphore - HelloWorld