高级同步器:倒计时门闩

  倒计时门闩会导致多天线程在“门口”一直等待,直到另一条线程打开这扇门,线程才得以继续运行。

类CountDownLatch提供一下方法:

void await(): 除非线程被中断,否则强制调用线程一直等到计数器倒数到0。

void countDown(): 递减计数,当计数降至0时,释放所有等待线程。当该方法调用时count已经为0,那么什么也不会发生。

long getCount(): 返回当前的计数。

String toString(): 返回一条标识这个门闩及其状态的字符串。

示例:

package com.thread;

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

/**
 * 高级同步器:倒计时门闩
 *     倒计时门闩会导致一条或者多条线程在“门口”一直等待(await()),直到另一条(例如主线程)打开这扇门,等待的线程才得以继续运行
 *     组成:计数变量和两个操作【1、导致线程等待直到计数变成0(startSignal),2、递减计数变量(doneSignal),确保线程完成工作】
 *     注意:递减计数变量不是必须的
 * @author Administrator
 *
 */
public class CountDownLatchDemo {
    
    final static int NTHREADS = 3;

    public static void main(String[] args) {
        final CountDownLatch startSignal = new CountDownLatch(1);
        final CountDownLatch doneSignal = new CountDownLatch(NTHREADS);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    report("entered run()");
                    startSignal.await();  //进来的线程进入等待,直到count=0
                    report("doing work");
                    Thread.sleep((int) (Math.random() * 1000));  //模拟线程各自工作耗时
                    doneSignal.countDown();  //当前线程计数减1,从3开始递减,确保3个线程都能完成工作
                                            
                }
                catch (InterruptedException ie) {
                    System.err.println(ie);
                }
            }

            void report(String s) {
                System.out.println(System.currentTimeMillis() + ": " + Thread.currentThread() + ": " + s);
            }
        };
        //创建3个线程的线程池,执行run方法
        ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
        for (int i = 0; i < NTHREADS; i++)
            executor.execute(r);
        try {
            //主线程等待1秒,确保三个线程都走到await()等待
            System.out.println("main thread doing something");
            Thread.sleep(1000);
            //计数器递减,递减到0时释放await上等待的线程,让三个线程同时开始工作
            //【startSignal count=1 是因为主线程唤醒线程池里的操作只需要一步,如果存在线程1计算sum1,线程2计算sum2,线程3对sum1和sum2求和,则count=2】
            startSignal.countDown();
            System.out.println("main thread doing something else");
            //等待所有线程执行完毕
            doneSignal.await();
            //关闭线程池
            executor.shutdownNow();
        } catch (InterruptedException ie) {
            System.err.println(ie);
        }
    }
    
    //main thread doing something
    //1554712657620: Thread[pool-1-thread-3,5,main]: entered run()
    //1554712657620: Thread[pool-1-thread-1,5,main]: entered run()
    //1554712657620: Thread[pool-1-thread-2,5,main]: entered run()
    //main thread doing something else
    //1554712658620: Thread[pool-1-thread-1,5,main]: doing work
    //1554712658621: Thread[pool-1-thread-2,5,main]: doing work
    //1554712658620: Thread[pool-1-thread-3,5,main]: doing work
}

 

posted @ 2019-04-08 17:06  x_jingxin  阅读(550)  评论(0编辑  收藏  举报