java中的线程(4):常用同步类 CountDownLatch、CyclicBarrier和Semaphore

转自:

  http://www.cnblogs.com/dolphin0520/p/3920397.html

1.简介

  • CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同。
  • CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行
  • CyclicBarrier 回环栅栏,一般用于一组线程互相等待至某个状态,然后这一组线程再同时开始执行后续任务
  • CountDownLatch 在使用完后不可重用
  • CyclicBarrier 使用完后可重用
  • Semaphore 信号量,一般用于控制对某组资源的访问权限。

2.CountDownLatch示例

 1    void testCountDownLatch() {
 2         final CountDownLatch latch = new CountDownLatch(2);
 3         new Thread() {
 4             public void run() {
 5                 try {
 6                     Log.d(TAG, "子线程" + Thread.currentThread().getName() + "正在执行");
 7                     Thread.sleep(3000);
 8                     Log.d(TAG, "子线程" + Thread.currentThread().getName() + "执行完毕");
 9                     latch.countDown();
10                 } catch (InterruptedException e) {
11                     e.printStackTrace();
12                 }
13             }
14 
15             ;
16         }.start();
17 
18         new Thread() {
19             public void run() {
20                 try {
21                     Log.d(TAG, "子线程" + Thread.currentThread().getName() + "正在执行");
22                     Thread.sleep(3000);
23                     Log.d(TAG, "子线程" + Thread.currentThread().getName() + "执行完毕");
24                     latch.countDown();
25                 } catch (InterruptedException e) {
26                     e.printStackTrace();
27                 }
28             }
29 
30             ;
31         }.start();
32 
33         try {
34             Log.d(TAG, "等待2个子线程执行完毕...");
35             latch.await();
36             Log.d(TAG, "2个子线程已经执行完毕");
37             Log.d(TAG, "继续执行主线程");
38         } catch (InterruptedException e) {
39             e.printStackTrace();
40         }
41     }

3.CyclicBarrier示例

  1 static class Writer extends Thread {
  2         private CyclicBarrier cyclicBarrier;
  3 
  4         public Writer(CyclicBarrier cyclicBarrier) {
  5             this.cyclicBarrier = cyclicBarrier;
  6         }
  7 
  8         @Override
  9         public void run() {
 10             Log.d(TAG, "线程" + Thread.currentThread().getName() + "正在写入数据...");
 11             try {
 12                 Thread.sleep(5000);      //以睡眠来模拟写入数据操作
 13                 Log.d(TAG, "线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");
 14                 cyclicBarrier.await();
 15             } catch (InterruptedException e) {
 16                 e.printStackTrace();
 17             } catch (BrokenBarrierException e) {
 18                 e.printStackTrace();
 19             }
 20             Log.d(TAG, "所有线程写入完毕,继续处理其他任务...");
 21         }
 22     }
 23 
 24 
 25     //用来阻塞当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
 26     void testCyclicBarrier1(){
 27         int N = 4;
 28         CyclicBarrier barrier = new CyclicBarrier(N);
 29         for (int i = 0; i < N; i++) {
 30             new Writer(barrier).start();
 31         }
 32     }
 33 
 34     //如果说想在所有线程写入操作完之后,进行额外的其他操作可以为CyclicBarrier提供Runnable参数
 35     void testCyclicBarrier2(){
 36         int N = 4;
 37         CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
 38             @Override
 39             public void run() {
 40                 Log.d(TAG, "当前线程" + Thread.currentThread().getName());
 41             }
 42         });
 43 
 44         for (int i = 0; i < N; i++){
 45             new Writer(barrier).start();
 46         }
 47     }
 48 
 49     //CyclicBarrier是可以重用的
 50     void testCyclicBarrier3(){
 51         int N = 4;
 52         CyclicBarrier barrier = new CyclicBarrier(N);
 53 
 54         for (int i = 0; i < N; i++) {
 55             new Writer(barrier).start();
 56         }
 57 
 58         try {
 59             Thread.sleep(25000);
 60         } catch (InterruptedException e) {
 61             e.printStackTrace();
 62         }
 63 
 64         Log.d(TAG, "CyclicBarrier重用");
 65 
 66         for (int i = 0; i < N; i++) {
 67             new Writer(barrier).start();
 68         }
 69     }
 70 
 71     //故意让最后一个线程启动延迟,因为在前面三个线程都达到barrier之后,
 72     //等待了指定的时间发现第四个线程还没有达到barrier,就抛出异常并继续执行后面的任务。
 73     void testCyclicBarrier4(){
 74 
 75         int N = 4;
 76         CyclicBarrier barrier = new CyclicBarrier(N);
 77 
 78         for (int i = 0; i < N; i++) {
 79             if (i < N - 1)
 80                 new Writer2(barrier).start();
 81             else {
 82                 try {
 83                     Thread.sleep(5000);
 84                 } catch (InterruptedException e) {
 85                     e.printStackTrace();
 86                 }
 87                 new Writer(barrier).start();
 88             }
 89         }
 90     }
 91     static class Writer2 extends Thread{
 92         private CyclicBarrier cyclicBarrier;
 93         public Writer2(CyclicBarrier cyclicBarrier) {
 94             this.cyclicBarrier = cyclicBarrier;
 95         }
 96 
 97         @Override
 98         public void run() {
 99             Log.d(TAG, "线程"+Thread.currentThread().getName()+"正在写入数据...");
100             try {
101                 Thread.sleep(5000);      //以睡眠来模拟写入数据操作
102                 Log.d(TAG, "线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
103                 try {
104                     cyclicBarrier.await(2000, TimeUnit.MILLISECONDS);//等待了指定的时间(2ms)发现第四个线程还没有达到barrier,就抛出异常并继续执行后面的任务
105                 } catch (TimeoutException e) {
106                     // TODO Auto-generated catch block
107                     e.printStackTrace();
108                 }
109             } catch (InterruptedException e) {
110                 e.printStackTrace();
111             }catch(BrokenBarrierException e){
112                 e.printStackTrace();
113             }
114             Log.d(TAG, Thread.currentThread().getName()+"所有线程写入完毕,继续处理其他任务...");
115         }
116     }

4.Semaphore示例

 1     void testSemaphore() {
 2         int N = 8;            //工人数
 3         Semaphore semaphore = new Semaphore(5); //机器数目
 4         for (int i = 0; i < N; i++)
 5             new Worker(i, semaphore).start();
 6     }
 7 
 8     static class Worker extends Thread {
 9         private int num;
10         private Semaphore semaphore;
11 
12         public Worker(int num, Semaphore semaphore) {
13             this.num = num;
14             this.semaphore = semaphore;
15         }
16 
17         @Override
18         public void run() {
19             try {
20                 semaphore.acquire();
21                 Log.d(TAG,"工人" + this.num + "占用一个机器在生产...");
22                 Thread.sleep(2000);
23                 Log.d(TAG,"工人" + this.num + "释放出机器");
24                 semaphore.release();
25             } catch (InterruptedException e) {
26                 e.printStackTrace();
27             }
28         }
29     }
原文地址:https://www.cnblogs.com/mhbs/p/7631502.html