用CountDownLatch实现在走完10个线程之后再进行操作

    在上一篇博客中,我们用Callable实现了这个功能:用Callable实现在走完10个线程之后再进行操作,其中也提到了使用CountDownLatch实现是一个更好地选择,下面,我们就来看看如何使用用CountDownLatch实现在走完10个线程之后再进行操作。                                                                                                                                                                                         我们先来看看《JAVA编程思想第四版》中对CountDownLatch的描述:

	CountDownLatch被用来同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。
	你可以向CcountDownLatch对象设置一个初始计数值,任何在这个对象上调用wait的方法都将阻塞,直至这个计数值到达0。
其他任务在结束其工作时,可以再该对象上调用countDown()来减小这个计数值。CountDownLatch被设计为只触发一次,计数值
不能被重置。如果你需要能够重置计数值的版本,则可以使用CyclicBarrier。
	调用countDown()的任务在产生这个调用时并没有被阻塞只有对await()的调用会被阻塞,直到计数值到达0.
	CountDownLatch的典型用法是将一个程序分为n个互相独立的可解决的任务,并创建值为0的CountDownLatch。(此处
应该是创建值为n的CountDownLatch)当每个任务完成时,都会在这个锁存器上调用countDown()。等待问题呗解决的
任务在这个锁存器上调用await(),将他们自己拦住,直到锁存器上技术结束。

再来看看具体要求的具体应用:

/**
 * 2018-05-05
 * @author liujie
 *
 */
public class TestCountDownLatch {
	public static void main(String[] args) throws Exception{
		int SIZE = 10;
		CountDownLatch latch = new CountDownLatch(SIZE);
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
		List<Runnable> threads = new ArrayList<Runnable>();
		for (int i = 0; i < SIZE; i++) {
			//多个任务线程共享一个CountDownLatch实例
			threads.add(new MyThread(latch));
		}
		for (Runnable runnable : threads) {
			Thread.sleep(50);
			cachedThreadPool.execute(runnable);
		}
		System.out.println("main Thread finished starting threads--" 
		+ new Date().getSeconds());
		//主线程会在这里等待,直到latch计数值到达0
		latch.await();
		//当latch计数值到达0,说明任务线程都完成了各自任务,主线程继续往下
		System.out.println("main Thread go on working--" + new Date().getSeconds());
	}
}
class MyThread implements Runnable{
	private CountDownLatch latch;
	private static transient int count = 0;
	private static Random random = new Random();
	private int id = count ++;
	public MyThread(CountDownLatch latch) {
		this.latch = latch;
	}
	public void run() {
		int workTimeSeconds = random.nextInt(10) + 1;
		System.out.println("Thread-" + id + "\tstart running for " 
		+ workTimeSeconds + " seconds--" + new Date().getSeconds());
		try {
			Thread.sleep(1000 * workTimeSeconds);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//在完成自己的任务后,将latch的计数值减一
		latch.countDown();
	}
}

以下是控制台的打印:

Thread-2	start running for 8 seconds--41
Thread-1	start running for 2 seconds--41
Thread-3	start running for 3 seconds--41
Thread-0	start running for 5 seconds--41
Thread-4	start running for 2 seconds--41
Thread-5	start running for 6 seconds--41
Thread-6	start running for 4 seconds--42
Thread-7	start running for 9 seconds--42
Thread-8	start running for 4 seconds--42
main Thread finished starting threads--42
Thread-9	start running for 1 seconds--42
main Thread go on working--51

由运行结果可知,程序实现了完成了题目的要求,主线程在第51秒的时候继续下面的任务,这是因为任务线程7是最后一个完成的任务(第42秒开始,耗时9秒,在51秒时完成).

我对CountDownLatch的理解:

    就相当于一个组长,在接到一个任务以后,将任务分为N份,并在一个任务计数器开启N个亮灯进行记录(new CountDownLath(N)),然后将这N份任务交给N个组员去完成(threadPool开启N个线程)。每个组员在接到任务后就各自忙自己的,在完成了他们的任务以后,就在任务计数器上熄灭一个灯(latch.countDown()),提示已经完成了自己的任务。有需要的人就会对这个任务计数器进行监控(latch.await()),直到所有的等都熄灭了,才会继续工作。

    


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章