对比 使用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成绩 英语全体学生成绩汇总计算 语文全体学生成绩汇总计算