转自:
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 }