java 倒计时闭锁——CountDownLatch的基本使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013276277/article/details/81558911

   CountDownLatch是一种灵活的闭锁,他可以使一个或者多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化为1个正数,表示需要等待的事件数量。countDown方法递减计数器,表示有一个事件已经发生了,而await方法等待计数器达到0,这表示所有需要等待的事件都已经发生。如果计数器的值非0,那么await会一直阻塞直到计数器为0,或者等待线程中的线程中断,或者等待超时。

    使用场景介绍:

(1) 确保某个计算在其需要的所有资源都被初始化之后才继续启动。

(2) 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。当启动服务s时,将首先在S依赖的其他服务的闭锁上等待,在所有有依赖的服务都启动后会释放闭锁S,这样其他依赖S的服务才能继续执行。

(3) 等待知道某个操作的所有参与者(例如,再多玩家游戏中的所有玩家)都就绪再继续执行。在这种情况中,当所有玩家准备就绪时,闭锁将到达结束状态。

    以下程序是测试多个线程执行某一任务所需要用到的时间。闭锁的应用在,当所有线程新建完并处于就绪状态时,才打开闭锁,所有线程一起并发执行。

package com.zy.charter5;

import java.util.concurrent.CountDownLatch;

public class TestHarness {
    
    public long  timeRasks(int nThreads, final Runnable task) {
        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(nThreads);
        
        for (int i =0; i < nThreads; i++) {
            Thread t = new Thread() {
                public void run() {
                    try {
                        startGate.await();// 在线程执行方法中阻塞住,也就是这边新建的线程都需要等待startGate的countDown()信号
                        try {
                            task.run();
                        } finally {
                            endGate.countDown(); // 执行完线程需要计数器见一,以便最后计算执行完所有线程所需要的时间
                        } 
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            t.start();// 开启线程,线程处于就绪状态,但是因为线程被startGate.await()阻塞住了还不能正常运行
            System.out.println(t.getName() + "可能要等待一会。。。");
        }
        long start = System.nanoTime();
        System.out.println("还没开始。。");
        startGate.countDown();// 计数减到0,全部被startGate.await()阻塞住的线程就会全部开始执行
        try {
            endGate.await();// 等待endGate.countDown()使所有线程执行完毕,好方便计算所有线程的执行时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        return end - start;
    }
    
    public static void main(String[] args) {
        System.out.println("time used : " + (new TestHarness()).timeRasks(5, new TaskRunnable()));
    }

}

class TaskRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "start to execute ...");
    }
    
}

执行结果:

Thread-0可能要等待一会。。。
Thread-1可能要等待一会。。。
Thread-2可能要等待一会。。。
Thread-3可能要等待一会。。。
Thread-4可能要等待一会。。。
还没开始。。
Thread-0start to execute ...
Thread-1start to execute ...
Thread-2start to execute ...
Thread-3start to execute ...
Thread-4start to execute ...
time used : 939077


 

猜你喜欢

转载自blog.csdn.net/u013276277/article/details/81558911