Java多线程之1-- CountDownLatch的用法
2017-02-16 12:42
405 查看
CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行,从而控制线程整体执行进度。与之对应的则是CyclicBarrier类。是等待到达某个公共屏障点后一起执行。具体看代码:
最后查看结果,你会发现,5个线程的开始时间和结束时间都是不一致的,照原来的线程调用方法,主线程在for循环完毕后就执行“========== finish for at...” 的那句打印,紧接着应该就是打印“all work done...” 的话,但是此处并没有这样,是因为latch.await()会等待所有线程执行完毕后才继续往下执行,因此你也就看到了“all work done at ”这句话在最后才执行。具体请看下图:
package thread; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class CountDownLatchDemo { final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException { Worker worker = null; ExecutorService excutorService = null; try{ List<String> names = Arrays.asList("张三", "李四", "王五", "牛六", "孙七"); // 此处用来控制同组线程的CountDownLatch,注意构造方法里面的参数必须和生成线程的总数相等 CountDownLatch latch = new CountDownLatch(names.size());// 两个工人的协作 // 线程执行器 excutorService = Executors.newCachedThreadPool(); // 线程名 String name = null; for (int i = 0; i < names.size(); i++) { name = names.get(i); // 线程初始化 worker = new Worker(name, latch); excutorService.execute(worker); // 错开每条线程的执行时间 TimeUnit.SECONDS.sleep(i); } // 等待所有工人完成工作 latch.await(); System.out.println("all work done at " + sdf.format(new Date())); }catch(Exception e){ e.printStackTrace(); }finally{ if(excutorService != null) { excutorService.shutdown(); } } } static class Worker implements Runnable { String workerName; int workTime; CountDownLatch latch; // 线程休眠时间 Random random; public Worker(String workerName, CountDownLatch latch) { this.workerName = workerName; this.latch = latch; random = new Random(); } public void run() { System.out.println("**** " + workerName + " begin at " + sdf.format(new Date())); // 工作了 doWork(); System.out.println("---- " + workerName + " end at " + sdf.format(new Date())); // 完成工作,计数器减一 latch.countDown(); } private void doWork() { try { TimeUnit.SECONDS.sleep(random.nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
最后查看结果,你会发现,5个线程的开始时间和结束时间都是不一致的,照原来的线程调用方法,主线程在for循环完毕后就执行“========== finish for at...” 的那句打印,紧接着应该就是打印“all work done...” 的话,但是此处并没有这样,是因为latch.await()会等待所有线程执行完毕后才继续往下执行,因此你也就看到了“all work done at ”这句话在最后才执行。具体请看下图:
**** 张三 begin at 2017-02-23 17:52:43 **** 李四 begin at 2017-02-23 17:52:43 ---- 张三 end at 2017-02-23 17:52:43 **** 王五 begin at 2017-02-23 17:52:44 ---- 王五 end at 2017-02-23 17:52:44 ---- 李四 end at 2017-02-23 17:52:45 **** 牛六 begin at 2017-02-23 17:52:46 **** 孙七 begin at 2017-02-23 17:52:49 ========== finish for at 2017-02-23 17:52:53 ---- 牛六 end at 2017-02-23 17:52:54 ---- 孙七 end at 2017-02-23 17:52:55 all work done at 2017-02-23 17:52:55