count计时器java,倒计时器CountDownLatch

1.背景:

countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。

存在于java.util.cucurrent包下。

2.概念

countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。

是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

3.使用场景

example1

为了能够理解CountDownLatch,举一个很通俗的例子,运动员进行跑步比赛时,假设有6个运动员参与比赛,裁判员在终点会为这6个运动员分别计时,

可以想象每当一个运动员到达终点的时候,对于裁判员来说就少了一个计时任务。直到所有运动员都到达终点了,裁判员的任务也才完成。这6个运动员可

以类比成6个线程,当线程调用CountDownLatch.countDown方法时就会对计数器的值减一,直到计数器的值为0的时候,裁判员(调用await方法的线程)

才能继续往下执行。

下面来看些CountDownLatch的一些重要方法。

先从CountDownLatch的构造方法看起:

public CountDownLatch(int count)

构造方法会传入一个整型数N,之后调用CountDownLatch的 countDown 方法会对N减一,知道N减到0的时候,当前调用 await 方法的线程继续执行。

CountDownLatch的方法不是很多,将它们一个个列举出来:

1. await() throws InterruptedException:调用该方法的线程等到构造方法传入的N减到0的时候,才能继续往下执行;

2. await(long timeout, TimeUnit unit):与上面的await方法功能一致,只不过这里有了时间限制,调用该方法的线程等到指定的timeout时间后,不管N是

否减至为0,都会继续往下执行;

3. countDown():使CountDownLatch初始值N减1;

4. long getCount():获取当前CountDownLatch维护的值;

下面用一个具体的例子来说明CountDownLatch的具体用法:

package com.example.demo.test;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

*

* @version V1.0 15:44 guozl

* @since 1.0

*/

public class CountDownLatchDemo {

private static CountDownLatch startSignal = new CountDownLatch(1);

//用来表示裁判员需要维护的是6个运动员

private static CountDownLatch endSignal = new CountDownLatch(6);

public static void main(String[] args) throws InterruptedException {

ExecutorService executorService = Executors.newFixedThreadPool(6);

for (int i = 0; i < 6; i++) {

executorService.execute(() -> {

try {

System.out.println(Thread.currentThread().getName() + " 运动员就位等待裁判员响哨!!!");

startSignal.await();

System.out.println(Thread.currentThread().getName() + "正在全力冲刺");

System.out.println(Thread.currentThread().getName() + " 到达终点");

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

endSignal.countDown();

}

});

}

Thread.sleep(1000);

System.out.println("裁判员发号施令啦!!!");

startSignal.countDown();

endSignal.await();

System.out.println("所有运动员到达终点,比赛结束!");

executorService.shutdown();

}

}

输出结果:

pool-1-thread-2 运动员就位等待裁判员响哨!!!

pool-1-thread-1 运动员就位等待裁判员响哨!!!

pool-1-thread-4 运动员就位等待裁判员响哨!!!

pool-1-thread-3 运动员就位等待裁判员响哨!!!

pool-1-thread-5 运动员就位等待裁判员响哨!!!

pool-1-thread-6 运动员就位等待裁判员响哨!!!

裁判员发号施令啦!!!

pool-1-thread-2正在全力冲刺

pool-1-thread-2 到达终点

pool-1-thread-3正在全力冲刺

pool-1-thread-3 到达终点

pool-1-thread-4正在全力冲刺

pool-1-thread-4 到达终点

pool-1-thread-5正在全力冲刺

pool-1-thread-5 到达终点

pool-1-thread-1正在全力冲刺

pool-1-thread-1 到达终点

pool-1-thread-6正在全力冲刺

pool-1-thread-6 到达终点

所有运动员到达终点,比赛结束!

该示例代码中设置了两个CountDownLatch,第一个 endSignal 用于控制让main线程(裁判员)必须等到其他线程(运动员)让CountDownLatch维护的

数值N减到0为止。另一个 startSignal 用于让main线程对其他线程进行“发号施令”,startSignal引用的CountDownLatch初始值为1,而其他线程执行的

run方法中都会先通过 startSignal.await() 让这些线程都被阻塞,直到main线程通过调用 startSignal.countDown(); ,将值N减

1,CountDownLatch维护的数值N为0后,其他线程才能往下执行,并且,每个线程执行的run方法中都会通

过 endSignal.countDown(); 对 endSignal 维护的数值进行减一,由于往线程池提交了6个任务,会被减6次,所以 endSignal 维护的值最终会变为0,

因此main线程在 latch.await(); 阻塞结束,才能继续往下执行。

另外,需要注意的是,当调用CountDownLatch的countDown方法时,当前线程是不会被阻塞,会继续往下执行,比如在该例中会继续输出 pool-1-

thread-4 到达终点 。

example2

模拟数据量较大 多线程分页查询处理

packagecom.example.demo.test;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;/*** CountDownLatch 的使用示例

*@versionV1.0 10:51 guozl

*@since1.0*/

public classCountDownLatchExample {//请求的数量(每页数量)

private static final int threadCount = 8;public static void main(String[] args) throwsInterruptedException {//定义j为页数

for (int j = 1; j < 3; j++) {

ExecutorService threadPool= Executors.newFixedThreadPool(5);final CountDownLatch countDownLatch = newCountDownLatch(threadCount);for (int i = 0; i < threadCount; i++) {final int threadnum =i;

threadPool.execute(()-> {//Lambda 表达式的运用

try{//实际业务操作

test(threadnum);

}catch(InterruptedException e) {

e.printStackTrace();

}finally{

countDownLatch.countDown();//表示一个请求已经被完成

}

});

}

countDownLatch.await();

threadPool.shutdown();

System.out.println("finish");

}

System.out.println("all finish");

System.out.println("处理所有数据业务操作");

}public static void test(int threadnum) throwsInterruptedException {

Thread.sleep(500);//模拟请求的耗时操作

System.out.println("threadnum:" +threadnum);

Thread.sleep(500);//模拟请求的耗时操作

}

}

执行结果:

threadnum:4

threadnum:2

threadnum:3

threadnum:0

threadnum:1

threadnum:7

threadnum:6

threadnum:5

finish

threadnum:2

threadnum:4

threadnum:0

threadnum:1

threadnum:3

threadnum:7

threadnum:6

threadnum:5

finish

all finish

处理所有数据业务操作

下一篇分享循环栅栏:CyclicBarrier  并与CountDownLatch做比较  有问题欢迎评论区交流 共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值