java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7311字,纯文字阅读大概需要11分钟。
内容图文
![java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用](/upload/InfoBanner/zyjiaocheng/1050/a6ec8f95e279462e9393981fc1d525c2.jpg)
先来讲解一下Semaphore信号灯的作用:
可以维护当前访问自身的线程个数,并提供了同步机制,
使用semaphore可以控制同时访问资源的线程个数
例如,实现一个文件允许的并发访问数。
请看下面的演示代码:
1 public class SemaphoreTest 2 { 3 public static void main(String[] args) 4 { 5 // 创建一个带有缓存的线程池 6 ExecutorService service = Executors.newCachedThreadPool(); 7//创建三个信号灯 8final Semaphore sp = new Semaphore(3);//最多并发三个线程 此处可以按照需求去修改 9//开启十个线程10for (int i = 1; i <= 10; i++) 11 { 12//只有三个线程可以同时进入 其余线程等待13 service.execute(new Runnable() 14 { 15 @Override 16publicvoid run() 17 { 18try19 { 20 sp.acquire();//获取一盏信号灯21 } catch (InterruptedException e) 22 { 23 e.printStackTrace(); 24 } 25 System.out.println("线程 "+Thread.currentThread().getName()+" 进入" 26 + " ,当前已有 "+(3-sp.availablePermits())+ " 个并发"); 27try28 { 29 Thread.sleep(new Random().nextInt(1000)); 30 } catch (InterruptedException e) 31 { 32 e.printStackTrace(); 33 } 34 System.out.println("线程 "+Thread.currentThread().getName()+" 即将离开 "); 35 sp.release();//释放36 System.out.println("线程 "+Thread.currentThread().getName()+" 已经离开" 37 + " ,当前已有 "+(3-sp.availablePermits())+ " 个并发"); 38 } 39 }); 40 } 41 service.shutdown(); 42 } 43 }
执行结果如下:
![技术分享](/img/jia.gif)
![技术分享](/img/jian.gif)
线程 pool-1-thread-2 进入 ,当前已有 2 个并发 线程 pool-1-thread-3 进入 ,当前已有 3 个并发 线程 pool-1-thread-1 进入 ,当前已有 3 个并发 线程 pool-1-thread-3 即将离开 线程 pool-1-thread-3 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-4 进入 ,当前已有 3 个并发 线程 pool-1-thread-1 即将离开 线程 pool-1-thread-5 进入 ,当前已有 3 个并发 线程 pool-1-thread-1 已经离开 ,当前已有 3 个并发 线程 pool-1-thread-2 即将离开 线程 pool-1-thread-2 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-6 进入 ,当前已有 3 个并发 线程 pool-1-thread-6 即将离开 线程 pool-1-thread-6 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-7 进入 ,当前已有 3 个并发 线程 pool-1-thread-7 即将离开 线程 pool-1-thread-7 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-8 进入 ,当前已有 3 个并发 线程 pool-1-thread-4 即将离开 线程 pool-1-thread-4 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-9 进入 ,当前已有 3 个并发 线程 pool-1-thread-5 即将离开 线程 pool-1-thread-5 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-10 进入 ,当前已有 3 个并发 线程 pool-1-thread-10 即将离开 线程 pool-1-thread-10 已经离开 ,当前已有 2 个并发 线程 pool-1-thread-8 即将离开 线程 pool-1-thread-8 已经离开 ,当前已有 1 个并发 线程 pool-1-thread-9 即将离开 线程 pool-1-thread-9 已经离开 ,当前已有 0 个并发
Semaphore信号灯可以控制并发数,保证每次最多只能有三个线程在线程池中。
CyclicBarrier类的使用,可以模拟现实生活中的多人等待上车的情形,例如多人去旅行,那么当A到达集合点时,不能立即出发,必须等到B也到达集合点,那么A和B必须等到C也到达集合点,此时,三人可以坐车出发去下一站。该类就可以实现此功能,请看如下代码。
1 public class CyclicBarrierTest 2 { 3 public static void main(String[] args) 4 { 5 // 创建一个带有缓存的线程池 6 ExecutorService service = Executors.newCachedThreadPool(); 7//指定三个线程 只有当三个线程同时到达时 程序才会往下执行 8final CyclicBarrier cb = new CyclicBarrier(3); 910for (int i = 0; i < 3; i++) 11 { 12 Runnable runnable = new Runnable() 13 { 14 @Override 15publicvoid run() 16 { 17try18 { 19/**20 * cb.getNumberWaiting():从0开始,获取当前等待的线程数量 21*/22//第一个23 Thread.sleep(new Random().nextInt(1000)); 24 System.out.println("线程 "+Thread.currentThread().getName()+" 即将到达集合地点1," 25 + "当前已有"+(cb.getNumberWaiting()+1)+" 个线程,"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在继续等待")); 26 cb.await();//让线程等待 2728//第二个29 Thread.sleep(new Random().nextInt(1000)); 30 System.out.println("线程 "+Thread.currentThread().getName()+" 即将到达集合地点2," 31 + "当前已有"+(cb.getNumberWaiting()+1)+" 个线程,"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在继续等待")); 32 cb.await(); 3334//第三个35 Thread.sleep(new Random().nextInt(1000)); 36 System.out.println("线程 "+Thread.currentThread().getName()+" 即将到达集合地点3," 37 + "当前已有"+(cb.getNumberWaiting()+1)+" 个线程,"+(cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在继续等待")); 38 cb.await(); 39 } catch (InterruptedException | BrokenBarrierException e) 40 { 41 e.printStackTrace(); 42 } 43 } 44 }; 45 service.execute(runnable); 46 } 4748 service.shutdown();//关闭线程池49 } 50 }
如下是执行结果:
![技术分享](/img/jia.gif)
![技术分享](/img/jian.gif)
1 线程 pool-1-thread-2 即将到达集合地点1,当前已有1 个线程,正在继续等待 2 线程 pool-1-thread-1 即将到达集合地点1,当前已有2 个线程,正在继续等待 3 线程 pool-1-thread-3 即将到达集合地点1,当前已有3 个线程,都到齐了,继续走啊 4 线程 pool-1-thread-2 即将到达集合地点2,当前已有1 个线程,正在继续等待 5 线程 pool-1-thread-1 即将到达集合地点2,当前已有2 个线程,正在继续等待 6 线程 pool-1-thread-3 即将到达集合地点2,当前已有3 个线程,都到齐了,继续走啊 7 线程 pool-1-thread-1 即将到达集合地点3,当前已有1 个线程,正在继续等待 8 线程 pool-1-thread-2 即将到达集合地点3,当前已有2 个线程,正在继续等待 9 线程 pool-1-thread-3 即将到达集合地点3,当前已有3 个线程,都到齐了,继续走啊
CountDownLatch计数器的使用:
* 演示一个计数器CountDownLatch
* 模拟百米赛跑
* 1个裁判 吹口哨
* 3个运动员
1 public class CountDownLatchTest 2 { 3 public static void main(String[] args) 4 { 5 // 创建一个带有缓存的线程池 6 ExecutorService service = Executors.newCachedThreadPool(); 7final CountDownLatch cdOrder = new CountDownLatch(1);//裁判 8final CountDownLatch cdAnswer = new CountDownLatch(3);//运动员 9for (int i = 0; i < 3; i++) 10 { 11 Runnable runnable = new Runnable() 12 { 13 @Override 14publicvoid run() 15 { 16try17 { 18 System.out.println("线程"+Thread.currentThread().getName()+" 正准备接收命令 "); 19 cdOrder.await();//等待计数器归0时 代码向下走20 System.out.println("线程"+Thread.currentThread().getName()+" 已接收命令 "); 21 Thread.sleep(new Random().nextInt(1000)); 22 System.out.println("线程"+Thread.currentThread().getName()+" 回应命令处理结果 "); 23 cdAnswer.countDown();//没调用一次该方法 就会将当前计数器上的计数减124 } catch (InterruptedException e) 25 { 26 e.printStackTrace(); 27 } 28 } 29 }; 30 service.execute(runnable); 31 } 323334//主线恒35try36 { 37 Thread.sleep(new Random().nextInt(1000)); 38 System.out.println("线程"+Thread.currentThread().getName()+" 即将发布命令 "); 39 cdOrder.countDown();//相当于把计数器身上的计数减140 System.out.println("线程"+Thread.currentThread().getName()+" 已发送命令,正在等待结果 "); 41 cdAnswer.await(); 42 System.out.println("线程"+Thread.currentThread().getName()+" 已收到所有相应结果"); 43 } catch (InterruptedException e) 44 { 45 e.printStackTrace(); 46 } 47 service.shutdown();//关闭线程池48 } 49 }
如下是执行结果:
![技术分享](/img/jia.gif)
![技术分享](/img/jian.gif)
1 线程pool-1-thread-1 正准备接收命令 2 线程pool-1-thread-2 正准备接收命令 3 线程pool-1-thread-3 正准备接收命令 4线程main 即将发布命令 5线程main 已发送命令,正在等待结果 6 线程pool-1-thread-1 已接收命令 7 线程pool-1-thread-2 已接收命令 8 线程pool-1-thread-3 已接收命令 9 线程pool-1-thread-2 回应命令处理结果 10 线程pool-1-thread-3 回应命令处理结果 11 线程pool-1-thread-1 回应命令处理结果 12 线程main 已收到所有相应结果
Exchanger类可以实现两个线程之间的数据交换:
1 public class ExchangerTest 2 { 3 public static void main(String[] args) 4 { 5 // 创建一个带有缓存的线程池 6 ExecutorService service = Executors.newCachedThreadPool(); 7final Exchanger<String> changer = new Exchanger<String>(); 8//开启第一个任务 9 service.execute(new Runnable() 10 { 11 @Override 12publicvoid run() 13 { 14try15 { 16 String dtail1 = "zhangsan";//准备要交换出去的数据17 System.out.println("线程 "+Thread.currentThread().getName()+" 正要把"+dtail1+"换出去"); 18 Thread.sleep(new Random().nextInt(1000)); 19 String dtail2 = changer.exchange(dtail1);//换回来的数据20 System.out.println("线程 "+Thread.currentThread().getName()+"换回的数据为"+dtail2); 21 } catch (InterruptedException e) 22 { 23 e.printStackTrace(); 24 } 25 } 26 }); 2728//开启第二个任务29 service.execute(new Runnable() 30 { 31 @Override 32publicvoid run() 33 { 34try35 { 36 String dtail1 = "lisi";//准备要交换出去的数据37 System.out.println("线程 "+Thread.currentThread().getName()+" 正要把"+dtail1+"换出去"); 38 Thread.sleep(new Random().nextInt(1000)); 39 String dtail2 = changer.exchange(dtail1);//换回来的数据40 System.out.println("线程 "+Thread.currentThread().getName()+"换回的数据为"+dtail2); 41 } catch (InterruptedException e) 42 { 43 e.printStackTrace(); 44 } 45 } 46 }); 47 service.shutdown(); 48 } 49 }
如下是执行结果:
![技术分享](/img/jia.gif)
![技术分享](/img/jian.gif)
1 线程 pool-1-thread-1 正要把zhangsan换出去 2 线程 pool-1-thread-2 正要把lisi换出去 3 线程 pool-1-thread-1换回的数据为lisi 4 线程 pool-1-thread-2换回的数据为zhangsan
以上都是java 5中的一些知识点,大家可以根据实际工作中的需要进行选择使用!!
原文:http://www.cnblogs.com/little-fly/p/7600549.html
内容总结
以上是互联网集市为您收集整理的java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用全部内容,希望文章能够帮你解决java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。