题目
假如有Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总,应当如何实现?
一、CountDownLantch方式
import java.util.concurrent.*;
import static java.lang.System.out;
public class MoreThreadPrint1 {
static int sumC=0;
static int sumD=0;
static int sumE=0;
static int sumF=0;
public static void main(String[] args) throws InterruptedException {
out.println();
//创建一个能容纳4个线程的减数器
final CountDownLatch countDownLatch= new CountDownLatch(4);
Runnable runC= new Runnable() {
@Override
public void run() {
try {
sumC=sumC+100;
System.out.println("统计C盘:"+sumC);
countDownLatch.countDown();//单任务,把计数器减1
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable runD= new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(1500);
sumD=sumD+200;
System.out.println("统计D盘:"+sumD);
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable runE= new Runnable() {
@Override
public void run() {
try {
sumE=sumE+300;
System.out.println("统计E盘:"+sumE);
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable runF= new Runnable() {
@Override
public void run() {
try {
sumF=sumF+400;
System.out.println("统计F盘:"+sumF);
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
ThreadPoolExecutor poll=new ThreadPoolExecutor(4,4,10L, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5),new ThreadPoolExecutor.DiscardOldestPolicy());
poll.submit(runC);
poll.submit(runD);
poll.submit(runE);
poll.submit(runF);
poll.shutdown();
//ExecutorService service= Executors.newFixedThreadPool(4);
//service.submit(runC);
//service.submit(runD);
//service.submit(runE);
//service.submit(runF);
countDownLatch.await();//主线程,即第5线程等待
int sum=sumC+sumD+sumE+sumF;
System.out.println("合计C,D,E,F:"+sum);
//service.shutdown();
}
}
二、CyclicBarrier方式
import java.util.concurrent.*;
public class MoreThreadPrint2 {
public static void main(String[] args) {
Runnable barrierAction = new Runnable() {
@Override
public void run() {
System.out.println("统计C,D,E,F盘");
}
};
final CyclicBarrier cyclicBarrier = new CyclicBarrier(4, barrierAction);
Runnable runC = new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(3000);
System.out.println("C盘");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
Runnable runD = new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(3000);
System.out.println("D盘");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
Runnable runE = new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(3000);
System.out.println("E盘");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
Runnable runF = new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(3000);
System.out.println("F盘");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
ThreadPoolExecutor poll = new ThreadPoolExecutor(4, 4, 10L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5), new ThreadPoolExecutor.DiscardOldestPolicy());
poll.submit(runC);
poll.submit(runD);
poll.submit(runE);
poll.submit(runF);
poll.shutdown();
}
}
三、Semaphore方式
import java.util.concurrent.*;
public class MoreThreadPrint3 {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(0);
Runnable barrierAction = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("统计C,D,E,F盘");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Semaphore semaphoreC=new Semaphore(1);
Semaphore semaphoreD=new Semaphore(0);
Semaphore semaphoreE=new Semaphore(0);
Semaphore semaphoreF=new Semaphore(0);
Runnable runC = new Runnable() {
@Override
public void run() {
try {
semaphoreC.acquire();
System.out.println("C盘");
semaphoreD.release();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable runD = new Runnable() {
@Override
public void run() {
try {
semaphoreD.acquire();
System.out.println("D盘");
semaphoreE.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable runE = new Runnable() {
@Override
public void run() {
try {
semaphoreE.acquire();
System.out.println("E盘");
semaphoreF.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable runF = new Runnable() {
@Override
public void run() {
try {
semaphoreF.acquire();
System.out.println("F盘");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ThreadPoolExecutor poll = new ThreadPoolExecutor(4, 4, 10L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5), new ThreadPoolExecutor.DiscardOldestPolicy());
poll.submit(runC);
poll.submit(runD);
poll.submit(runE);
poll.submit(runF);
poll.submit(barrierAction);
poll.shutdown();
}
}
小结
最后一种方式能保证按顺序执行,因为信号量的获取和释放是有次序的。