CountDownLatch

  1. 云栖社区>
  2. 博客>
  3. 正文

CountDownLatch

developerguy 2015-11-20 23:21:00 浏览402
展开阅读全文


一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。
之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。
这种现象只出现一次——计数无法被重置。(如果CountDownLatch实例是一个对象的字段,这个对象相同的方法非第一次被调用,则无法出现排队等待的情况)
 

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行。CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。

CountDownLatch的一个非常典型的应用场景是:
有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。
假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

 

package thread.cyclic;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * CountDownLatch是个计数器,它有一个初始数, 等待这个计数器的线程必须等到计数器倒数到零时才可继续。
 */
public class CountDownLatchTest {

    /**
     * 初始化组件的线程
     */
    public static class ComponentThread implements Runnable {
        // 计数器
        CountDownLatch latch;
        // 组件ID
        int id;

        // 构造方法
        public ComponentThread(CountDownLatch latch, int id) {
            this.latch = latch;
            this.id = id;
        }

        public void run() {
            // 初始化组件
            System.out.println(Thread.currentThread() + "Initializing component " + id);
            try {
                TimeUnit.SECONDS.sleep(id);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + "Component " + id + " initialized!");
            // 将计数器减一
            latch.countDown();
        }
    }

    /**
     * 启动服务器
     */
    public static void startServer() throws Exception {
        System.out.println(Thread.currentThread() + "Server is starting.");
        // 初始化一个初始值为3的CountDownLatch
        CountDownLatch latch = new CountDownLatch(3);
        // 起3个线程分别去启动3个组件
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(new ComponentThread(latch, 1));
        service.submit(new ComponentThread(latch, 2));
        service.submit(new ComponentThread(latch, 3));
        service.shutdown();
        // 等待3个组件的初始化工作都完成
        latch.await();
        // 当所需的三个组件都完成时,Server就可继续了
        System.out.println(Thread.currentThread() + "Server is up!");
    }

    public static void main(String[] args) throws Exception {
        CountDownLatchTest.startServer();
    }
}

Output:

Thread[main,5,main]Server is starting.
Thread[pool-1-thread-1,5,main]Initializing component 1
Thread[pool-1-thread-2,5,main]Initializing component 2
Thread[pool-1-thread-3,5,main]Initializing component 3
Thread[pool-1-thread-1,5,main]Component 1 initialized!
Thread[pool-1-thread-2,5,main]Component 2 initialized!
Thread[pool-1-thread-3,5,main]Component 3 initialized!
Thread[main,5,main]Server is up!

http://blog.csdn.net/huang_xw/article/details/7090146
http://www.iteye.com/topic/657295

 

网友评论

登录后评论
0/500
评论
developerguy
+ 关注