Java并发包中提供了很多有用的工具类来帮助开发者进行并发编程,今天我就来说说CountDownLatch,CyclicBarrier以及Semaphore这三个的用法和使用场景。
1.CountDownLatch使用场景和用法
CountDownLatch一般是用于某个线程等待其他线程执行完之后,它才能执行。例如一家人在等待爸爸妈妈回家,才能进行晚宴,示例代码如下:
public class CountDownLatchTest { public static void main(String[] args) throws Exception { final CountDownLatch cdl = new CountDownLatch(2); new Thread(){ public void run() { try { System.out.println("等待老爸回家..."); Thread.sleep(5000); cdl.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); new Thread(){ public void run() { try { System.out.println("等待老妈回家..."); Thread.sleep(5000); cdl.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); cdl.await(); System.out.println("老爸老妈回来了..."); System.out.println("晚宴开始了..."); } }
public class CyclicBarrierTest { public static void main(String[] args) { int count = 3; CyclicBarrier cb = new CyclicBarrier(count, new Runnable() { @Override public void run() { //此处所有线程都调用了await方法之后,会走到这里 System.out.println("所有线程操作完成之后都调用了await方法"); } }); for(int i=0;i<count;i++){ new WriteLogHandler(cb).start(); } } static class WriteLogHandler extends Thread{ private CyclicBarrier cb = null; public WriteLogHandler(CyclicBarrier cb) { this.cb = cb; } @Override public void run() { try { System.out.println("线程:" + Thread.currentThread().getName() + "开始写日志"); Thread.sleep(2000); System.out.println("线程:" + Thread.currentThread().getName() + "写日志结束,等待其他线程"); cb.await(); System.out.println("所有线程写日志数据结束,继续其他操作"); } catch (Exception e) { e.printStackTrace(); } } } }
public class SemaphoreTest { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(5); for(int i=0;i<10;i++){ final int num = i; executor.execute(new Runnable() { @Override public void run() { try { semaphore.acquire(); System.out.println("正在执行任务" + num); Thread.sleep((long)Math.random() * 1000); System.out.println("任务" + num + "执行结束"); semaphore.release(); } catch (Exception e) { e.printStackTrace(); } } }); } executor.shutdown(); } }