学习CountDownLatch
对比 使用CyclicBarrier
上次用Barrier方式实现了线程等待一组完成,这次用CountDownLatch来实现
我的理解CountDownLatch 采用的方式是计数器方式,每执行完一个线程,计数器减一,等计数器减到0的时候,之前等待的线程就可以执行了。
和Barrier的例子一样,这次是2个线程等待一组完成,代码如下:
package countdown; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo { public static void main(String[] args) { List<String> students = Arrays.asList("Tom","Bill","Dick","Marry","Lily","Harry"); StudentCalc calc = new StudentCalc(); CountDownLatch cdl= new CountDownLatch(students.size());//算是个计数器吧 ExecutorService exec = Executors.newCachedThreadPool();//用线程池方式执行 exec.execute(new TotalScore(cdl,new StudentCalc("语文")));//汇总任务 exec.execute(new TotalScore(cdl,new StudentCalc("英语")));//汇总任务 students.forEach(x->exec.execute(new StudentScore(cdl,calc,x)));//每个学生的任务 exec.shutdown();//关闭线程池 } } class StudentScore implements Runnable{ private StudentCalc studentCalc; private String studentName; private CountDownLatch countDownLatch; public StudentScore( CountDownLatch cdl, StudentCalc studentCalc, String studentName) { this.countDownLatch=cdl; this.studentCalc = studentCalc; this.studentName = studentName; } @Override public void run() { studentCalc.student(studentName); countDownLatch.countDown();//计算之后计数器-1 } } class TotalScore implements Runnable{ private StudentCalc studentCalc; private CountDownLatch countDownLatch; TotalScore(CountDownLatch cdl, StudentCalc studentCalc) { this.studentCalc = studentCalc; this.countDownLatch = cdl; } @Override public void run() { try { countDownLatch.await();//先等待所有线程完成 } catch (InterruptedException e) { e.printStackTrace(); } studentCalc.total();//总成绩 计算 } } /** * 计算类 */ class StudentCalc { private String type; public StudentCalc(String type) { this.type = type; } public StudentCalc() { } /** * 全部成绩计算完成后,调用汇总 */ public void total(){ System.out.println(type + "全体学生成绩汇总计算"); } /** * 计算每个学生自己成绩,为了模拟每个学生计算时间不同,使用Thread.sleep区分 * @param student */ public void student(String student){ try { Thread.sleep(new Random().nextInt(2000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算" + student + "成绩"); } }
执行结果如下:
计算Lily成绩 计算Bill成绩 计算Harry成绩 计算Marry成绩 计算Dick成绩 计算Tom成绩 英语全体学生成绩汇总计算 语文全体学生成绩汇总计算