JAVA并发 闭锁、同步屏障、信号量总结
闭锁 CountDownLatch
多个线程,其中一个线程要求要前几个线程准备完所需的资源后才运行。
代码实现
1 CountDownLatch latch=new CountDownLatch(2);//若有多条线程只能够等待指定线程完成后才能继续下一个指定线程 2 Thread t1=new Thread(new Runnable() { 3 4 @Override 5 public void run() { 6 // TODO Auto-generated method stub 7 latch.countDown();//本资源加载完成后闭锁-1; 8 } 9 }); 10 t1.start(); 11 Thread t2=new Thread(new Runnable() { 12 13 @Override 14 public void run() { 15 // TODO Auto-generated method stub 16 latch.countDown(); 17 } 18 }); 19 t2.start(); 20 21 Thread t3=new Thread(new Runnable() { 22 23 @Override 24 public void run() { 25 // TODO Auto-generated method stub 26 try { 27 latch.await(); 28 } catch (InterruptedException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 System.out.println("ok"); 33 } 34 }); 35 t3.start();
同步屏障CyclicBarrier
若有多条线程,他们到达屏障时将会被阻塞,只有当所有线程都到达屏障时才能打开屏障,所有线程同时执行,若有这样的需求可以使用同步屏障。此外,当屏障打开的同时还能指定执行的任务。
代码实现
1 2 CyclicBarrier barrier=new CyclicBarrier(3,new Runnable() { 3 4 @Override 5 public void run() { 6 // TODO Auto-generated method stub 7 System.out.println("一起"); 8 } 9 }); 10 11 for(int i=0;i<3;i++) { 12 new Thread(new Runnable() { 13 14 @Override 15 public void run() { 16 // TODO Auto-generated method stub 17 try { 18 barrier.await(); 19 } catch (InterruptedException | BrokenBarrierException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } 23 } 24 }).start(); 25 }
信号量:Semaphore
若有m个资源,但有n条线程(n>m),因此同一时刻只能允许m条线程访问资源,此时可以使用Semaphore控制访问该资源的线程数量。
代码实现
1 Semaphore semaphore=new Semaphore(3); 2 3 for(int i=0;i<10;i++) { 4 new Thread(new Runnable() { 5 6 @Override 7 public void run() { 8 // TODO Auto-generated method stub 9 try { 10 semaphore.acquire(); 11 } catch (InterruptedException e) { 12 // TODO Auto-generated catch block 13 e.printStackTrace(); 14 } 15 //................... 16 //..................... 17 semaphore.release(); 18 } 19 }).start(); 20 }
闭锁和同步屏障的区别
- 闭锁只会阻塞一条线程,目的是为了让该条任务线程满足条件后执行;
- 而同步屏障会阻塞所有线程,目的是为了让所有线程同时执行(实际上并不会同时执行,而是尽量把线程启动的时间间隔降为最少)。