您的位置:首页 > 职场人生

黑马程序员-Semaphore、CyclicBarrier、CountDownLatch、Exchanger

2013-03-05 23:08 573 查看
------- android培训java培训、期待与您交流! ----------

信号灯同步Semaphore:

  创建:Semaphore semaphore = new Semaphore(3);

  获取:semaphore.acquire();

  释放:semaphore.release();

  获取剩余信号灯数量:semaphore.availablePermits();

信号灯在创建的时候就定义一个数字允许有多少个信号灯,有很多线程,在执行的时候获取信号灯,如果信号灯获取等于了创建的个数,其余线程就等待,每个线程结束前释放一个线程获取的信号灯,等待的线程就开始抢这个空出来的信号灯,也可以在创建信号灯的时候指定是否公平排队,如果在构造函数中多加一个true的话,这个空出来的信号灯是分配给在等待的第一个线程,如同notify()一样的机制。

1     public static void main(String[] args) {
2         // TODO Auto-generated method stub
3         // 创建一个缓存线程池
4         ExecutorService threadPool = Executors.newCachedThreadPool();
5         // 创建有3个信号灯的信号灯对象
6         final Semaphore semaphore = new Semaphore(3);
7         for (int i = 0; i < 10; i++) {
8             new Thread(new Runnable() {
9
10                 @Override
11                 public void run() {
12                     try {
13                         // 获取一个信号灯
14                         semaphore.acquire();
15                         System.out.println(Thread.currentThread().getName() + "进来了");
16                         Thread.sleep(1000);
17                         //semaphore.availablePermits();获得剩余几个信号灯
18                         System.out.println("还有几个坑呢? :" + semaphore.availablePermits());
19                         System.out.println(Thread.currentThread().getName() + "准备闪了");
20
21                     } catch (Exception e) {
22
23                     }finally{
24                         // 释放一个信号灯
25                         semaphore.release();
26                     }
27                 }
28             }).start();
29         }
30     }


信号灯可以有效的控制几个线程同时运行。

关卡CyclicBarrier:

  创建:CyclicBarrier cb = new CyclicBarrier(3);// 创建对象并设置障碍需要3个线程一起通过

  设置关卡:cb.await();

  获得当前关卡前的线程数:cb.getNumberWaiting();//这个是从0开始记的,也就是说0就是代表有一个线程了。

这个可以用来制作游戏过关需要多少人啊,活动需要多少人参加才开启啊。

1     public static void main(String[] args) {
2         // TODO Auto-generated method stub
3         // 创建缓存线程池
4         ExecutorService threadPool = Executors.newCachedThreadPool();
5         // 创建对象并设置障碍需要3个线程一起通过
6         final CyclicBarrier cb = new CyclicBarrier(3);
7         for (int i = 0; i < 3; i++) {
8             threadPool.execute(new Runnable() {
9
10                 @Override
11                 public void run() {
12                     try {
13                         Thread.sleep((int) (Math.random() * 1000));
14                         System.out.println(Thread.currentThread().getName()
15                                 + "等待");
16                         //获取等待个数从0开始算
17                         if (cb.getNumberWaiting() == 2)
18                             System.out.println("人齐了,走你!");
19                         // 设置关卡、障碍
20                         cb.await();
21
22                         Thread.sleep((int) (Math.random() * 1000));
23                         System.out.println(Thread.currentThread().getName()
24                                 + "等待");
25                         if (cb.getNumberWaiting() == 2)
26                             System.out.println("人齐了,再走你!");
27                         // 设置关卡、障碍
28                         cb.await();
29                     } catch (Exception e) {
30                         // TODO: handle exception
31                     }
32                 }
33             });
34         }
35     }


倒记时锁存器CountDownLatch:

  创建:CountDownLatch cdl = new CountDownLatch(1);//计数器初始值为1

  等待计数器为0:cdl.await();

  计数器自减:cdl.countDown();

模拟运动员比赛等待裁判鸣枪,裁判等待所有运动员跑完然后公布结果。

1     public static void main(String[] args) {
2         // TODO Auto-generated method stub
3         //创建缓存线程池
4         ExecutorService threadPool = Executors.newCachedThreadPool();
5         //创建倒记时锁存器 ,计数器初始值为1
6         final CountDownLatch cdl = new CountDownLatch(1);
7         //计数器初始值为3
8         final CountDownLatch cdl2 = new CountDownLatch(3);
9         for(int i = 0; i < 3; i++){
10             threadPool.execute(new Runnable() {
11
12                 @Override
13                 public void run() {
14                     System.out.println("运动员"+Thread.currentThread().getName() + "等待命令");
15
16                     try {
17                         //等待cdl计数器为0
18                         cdl.await();
19                         Thread.sleep((int)(Math.random()*1000));
20                         System.out.println("运动员"+Thread.currentThread().getName() + "等待结果");
21
22                         //cdl2计数器自减
23                         cdl2.countDown();
24                     } catch (Exception e) {
25                         e.printStackTrace();
26                     }
27                 }
28             });
29         }
30         try {
31             Thread.sleep((int)(Math.random()*1000));
32
33             System.out.println("裁判 " + Thread.currentThread().getName() + " 鸣枪");
34             //cdl计数器自减
35             cdl.countDown();
36             System.out.println("裁判 " + Thread.currentThread().getName() + "等待运动员跑完公布结果");
37             //等待cdl2计数器为零
38             cdl2.await();
39             System.out.println("公布结果");
40         } catch (Exception e) {
41             // TODO: handle exception
42         }
43     }


控制台输出:

运动员pool-1-thread-1等待命令

运动员pool-1-thread-3等待命令

运动员pool-1-thread-2等待命令

裁判 main 鸣枪

裁判 main等待运动员跑完公布结果

运动员pool-1-thread-1等待结果

运动员pool-1-thread-3等待结果

运动员pool-1-thread-2等待结果

公布结果

交换工具类Exchanger:

  创建:Exchanger exchanger = new Exchanger();

  调用:String data2 = (String)exchanger.exchange(data1);

    String data2 = (String)exchanger.exchange(data1,2,TimeUnit.SECONDS);//这种表示在交换过程等待的时间要在两秒以内,如果超过两秒会抛出超时异常。

  

1     public static void main(String[] args) {
2         // TODO Auto-generated method stub
3         //创建交换工具类
4         final Exchanger exchanger = new Exchanger();
5         new Thread(new Runnable() {
6
7             @Override
8             public void run() {
9                 // TODO Auto-generated method stub
10                 try {
11                     String data1 = "zhangsan";
12                     System.out.println(Thread.currentThread().getName() + "要把zhangsan换出去");
13 //                    Thread.sleep(3000);
14                     //交换时等待的时间要在2秒内,否则抛出超时异常:TimeoutException
15                     //String data2 = (String)exchanger.exchange(data1,2,TimeUnit.SECONDS);
16                     //交换
17                     String data2 = (String)exchanger.exchange(data1);
18                     System.out.println(Thread.currentThread().getName() + "得到的:" + data2);
19                 } catch (Exception e) {
20                     e.printStackTrace();
21                 }
22             }
23         }).start();
24         new Thread(new Runnable() {
25
26             @Override
27             public void run() {
28                 // TODO Auto-generated method stub
29                 try {
30                     String data1 = "lisi";
31                     System.out.println(Thread.currentThread().getName() + "要把lisi换出去");
32                     Thread.sleep(3000);
33                     //交换
34                     String data2 = (String)exchanger.exchange(data1);
35                     System.out.println(Thread.currentThread().getName() + "得到的:" + data2);
36                 } catch (InterruptedException e) {
37                     e.printStackTrace();
38                 }
39             }
40         }).start();
41     }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐