• java多线程学习-java.util.concurrent详解(一) CountDownLatch


    转载于:http://janeky.iteye.com/blog/769965

    1. CountDownLatch 
        我们先来学习一下JDK1.5 API中关于这个类的详细介绍: 
    “一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。” 

        这就是说,CountDownLatch可以用来管理一组相关的线程执行,只需在主线程中调用CountDownLatch 的await方法(一直阻塞),让各个线程调用countDown方法。当所有的线程都只需完countDown了,await也顺利返回,不再阻塞了。在这样情况下尤其适用:将一个任务分成若干线程执行,等到所有线程执行完,再进行汇总处理。 

        下面我举一个非常简单的例子。假设我们要打印1-100,最后再输出“Ok“。1-100的打印顺序不要求统一,只需保证“Ok“是在最后出现即可。 

        解决方案:我们定义一个CountDownLatch,然后开10个线程分别打印(n-1)*10+1至(n-1)*10+10。主线程中调用await方法等待所有线程的执行完毕,每个线程执行完毕后都调用countDown方法。最后再await返回后打印“Ok”。 

    具体代码如下(本代码参考了JDK示例代码): 

    package com.winterbe.java8.samples.concurrent;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 示例:CountDownLatch的使用举例 Mail: ken@iamcoding.com
     * 等待所有的线程都执行完成后,再执行下面的步骤
     * 
     * @author janeky
     */
    public class TestCountDownLatch {
    	private static final int N = 10;
    
    	public static void main(String[] args) throws InterruptedException {
    		CountDownLatch doneSignal = new CountDownLatch(N);//N为要控制的线程的数量
    		CountDownLatch startSignal = new CountDownLatch(1);// 开始执行信号
    
    		for (int i = 1; i <= N; i++) {
    			new Thread(new Worker(i, doneSignal, startSignal)).start();// 线程启动了
    		}
    		System.out.println("begin------------");
    		startSignal.countDown();// 开始执行啦
    
    		doneSignal.await();// 等待所有的线程执行完毕,在所有线程未执行完成之前(doneSignal.getCount()>0),await()方法会受阻
    		System.out.println("Ok");
    
    	}
    
    	static class Worker implements Runnable {
    		private final CountDownLatch doneSignal;
    		private final CountDownLatch startSignal;
    		private int beginIndex;
    
    		Worker(int beginIndex, CountDownLatch doneSignal,
    				CountDownLatch startSignal) {
    			this.startSignal = startSignal;
    			this.beginIndex = beginIndex;
    			this.doneSignal = doneSignal;
    		}
    
    		public void run() {
    			try {
    				startSignal.await(); // 等待开始执行信号的发布
    				beginIndex = (beginIndex - 1) * 10 + 1;
    				for (int i = beginIndex; i <= beginIndex + 10; i++) {
    					System.out.println(i);
    				}
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			} finally {
    				System.out.println("done Count"+doneSignal.getCount());
    				doneSignal.countDown();//表示一个线程执行完成
    				System.out.println("colsed done Count"+doneSignal.getCount());
    			}
    		}
    	}
    }
    

      总结:CounDownLatch对于管理一组相关线程非常有用。上述示例代码中就形象地描述了两种使用情况。第一种是计算器为1,代表了两种状态,开关。第二种是计数器为N,代表等待N个操作完成。今后我们在编写多线程程序时,可以使用这个构件来管理一组独立线程的执行。 

    个人理解:如果某个步骤,需要在所有的线程都执行完成后,才能执行,CounDownLatch刚好可以管理该组进程。

  • 相关阅读:
    elemeng-ui中el-select的默认选择项问题
    element-ui的rules中正则表达式
    时间戳格式化
    array排序(按数组中对象的属性进行排序)
    vue-router路由传参
    flex属性flex-grow、flex-shrink、flex-basis
    sessionStorage、localStorage与cookie
    并发编程学习之线程可见性
    JVM系列文章合集
    JVM(1):Java 类的加载机制
  • 原文地址:https://www.cnblogs.com/fanxiaojun/p/4914267.html
Copyright © 2020-2023  润新知