一、基础篇--1.3进程和线程-CountDownLatch、CyclicBarrier 和 Semaphore
下面对上面说的三个辅助类进行一个总结:
1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:
CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限或者限流等等。
下面是几个小例子
public class CountDownLatchDemo { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); System.out.println("等爸爸妈妈都来了就吃饭"); new Thread(new Runnable() { @Override public void run() { try { System.out.println("爸爸过来了"); Thread.sleep(3000); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); new Thread(new Runnable() { @Override public void run() { try { System.out.println("妈妈过来了"); Thread.sleep(3000); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); try { latch.await(); System.out.println("开饭了"); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class CyclicbarrierDemo { public static void main(String[] args) { int no = 3; final CyclicBarrier cyclicBarrier = new CyclicBarrier(no, new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"发令员:3---2---1,跑!"); } }); for (int i = 0; i < no; i++) { new Thread(new Sportsman(cyclicBarrier)).start(); } } static class Sportsman implements Runnable{ CyclicBarrier cyclicBarrier; public Sportsman(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { try { Thread.sleep((int)(Math.random()*1000)); System.out.println(Thread.currentThread().getName()+"准备好了,等待发令枪"); cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"突突突"); } } }
public class SemaphoreDemo { public static void main(String[] args) { final Semaphore semaphore = new Semaphore(3); new Thread(new Runnable() { @Override public void run() { try { semaphore.acquire(3); System.out.println(Thread.currentThread().getName()+"获取3个许可证"); Thread.sleep(2000L); }catch (Exception e){ e.printStackTrace(); }finally { semaphore.release(3); } } }).start(); new Thread(new Runnable() { @Override public void run() { boolean flag = false; try { flag = semaphore.tryAcquire(1, 1, TimeUnit.SECONDS); if(flag){ System.out.println(Thread.currentThread().getName()+"获取一个许可证"); }else { System.out.println(Thread.currentThread().getName()+"获取失败!不能进入"); } }catch (Exception e){ e.printStackTrace(); }finally { if(flag){ //可以释放其他线程的信号量,如果没有获取到,不要释放,不然会有问题 semaphore.release(); } } } }).start(); } }