也是网上看的一道题目:关于假如有Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总,应当如何实现?
搜集整理了网上朋友提供的方法,主要有:
1. 多线程都是Thread或者Runnable(后者比较多),但是,这两种都是没返回值的,所以我们需要使用callable(有返回值的多线程)和future(获得线程的返回值)来实现了。
public class TestThread {
public static void main(String[] args) {
ThreadCount tc = null;
ExecutorService es = Executors.newCachedThreadPool();//线程池
CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(es);
for(int i=0;i<4;i++){
tc = new ThreadCount(i+1);
cs.submit(tc);
}
// 添加结束,及时shutdown,不然主线程不会结束
es.shutdown();
int total = 0;
for(int i=0;i<4;i++){
try {
total+=cs.take().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("总大小 = "+total);
}
}
class ThreadCount implements Callable<Integer>{
private int type;
ThreadCount(int type){
this.type = type;
}
@Override
public Integer call() throws Exception {
if(type==1){
System.out.println("C盘统计大小");
return 1;
}else if(type==2){
System.out.println("D盘统计大小");
return 2;
}else if(type==3){
System.out.println("E盘统计大小");
return 3;
}else if(type==4){
System.out.println("F盘统计大小");
return 4;
}
return null;
}
}
输出结果:
D盘统计大小
C盘统计大小
E盘统计大小
F盘统计大小
总大小 = 10
分析:四个线程实现的是Collable接口,执行完成后返回的值会存放与队列中,用cs.take.get()获取返回值获取队列中的值
2.用Java.util.concurrent下的方法解决
用CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行
CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
public class CountDownLatchDemo {
final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch=new CountDownLatch(4);//两个工人的协作
Worker worker1=new Worker("C", 1000, latch);
Worker worker2=new Worker("D", 1000, latch);
Worker worker3=new Worker("E", 1000, latch);
Worker worker4=new Worker("F", 1000, latch);
worker1.start();//
worker2.start();//
worker3.start();//
worker4.start();//
latch.await();//等待所有工人完成工作
System.out.println("all work done at "+sdf.format(new Date()));
System.out.println(Worker.count);
}
static class Worker extends Thread{
static int count = 0;
String workerName;
int workTime;
CountDownLatch latch;
public Worker(String workerName ,int workTime ,CountDownLatch latch){
this.workerName=workerName;
this.workTime=workTime;
this.latch=latch;
}
public void run(){
synchronized (Worker.class) {
System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));
int random = new Random().nextInt(5)+1;
System.out.println("Worker "+workerName+" size = "+random);
count = count + random;
System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));
latch.countDown();//工人完成工作,计数器减一
}
}
}
}
输出结果:
Worker C do work begin at 2018-11-08 00:23:34
Worker C size = 5
Worker C do work complete at 2018-11-08 00:23:34
Worker F do work begin at 2018-11-08 00:23:34
Worker F size = 4
Worker F do work complete at 2018-11-08 00:23:34
Worker E do work begin at 2018-11-08 00:23:34
Worker E size = 1
Worker E do work complete at 2018-11-08 00:23:34
Worker D do work begin at 2018-11-08 00:23:34
Worker D size = 4
Worker D do work complete at 2018-11-08 00:23:34
all work done at 2018-11-08 00:23:34
14
分析:count中存放的是当前统计完成后的总大小,当4个盘的统计线程都完成以后,这个时候就可以执行线程5,这个与上面的区别是前面的线程执行完后没有返回值,只能确定线程执行完成了,但却没有返回值。汇总统计没有放在线程5中,前面4个统计线程执行完成以后,汇总统计结果已经出来了。