Java并发30:CountDownLatch(上)--基本方法学习
2018-03-31 22:29
567 查看
[超级链接:Java并发学习系列-绪论]
本章主要对CountDownLatch的基本方法进行学习。
有关CountDownLatch的应用实例详见下一章:《Java并发:31》
所谓CountDown即 倒计时 的意思,所谓Latch即 门闩 的意思。
所以综合起来,CountDownLatch指的就是 倒计时门闩,虽然这个叫法很奇怪,但是确能很好地表示它的作用。
其作用在JDK注释中是这样描述的:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
简单来说,CountDownLatch就是一种同步辅助工具类,这个工具类实现的效果是:
让一个或多个线程持续等待,直到其他多线程执行的一组操作全部完成以后,这些等待的线程才会继续执行。
引用[July 18, 2013 by Lokesh Gupta]的一段话和图:
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。
每当一个线程完成了自己的任务后,计数器的值就会减1。
当计数器值到达0时,它表示所有的线程已经完成了任务,然后在等待的线程就可以恢复执行任务。
getCount():获取当前count的值。
wait():让当前线程在此CountDownLatch对象上等待,可以中断。与notify()、notifyAll()方法对应。
await():让当前线程等待此CountDownLatch对象的count变为0,可以中断。
await(timeout,TimeUnit):让当前线程等待此CountDownLatch对象的count变为0,可以超时、可以中断。
countDown():使此CountDownLatch对象的count值减1(无论执行多少次,count最小值为0)。
注意:
wait()是从Object类继承来的,关于它的用法,请参加《Java并发07》,这里不再赘述。
无论执行多少次countDown(),count最小值为0,不会变成负数。
练习目的:熟悉await():、await(timeout,TimeUnit):和countDown():的基本用法。
共计编写5个线程:
thread-0 : 等待方法-await(),终止原因-latch.count=0
thread-1 : 等待方法-await(),终止原因-thread.interrupt()
thread-2 : 等待方法-await(timeout,TimeUnit),终止原因- await timeout
thread-3 : 等待方法-await(timeout,TimeUnit),终止原因- thread.interrupt()
thread-4 : 等待方法-await(timeout,TimeUnit),终止原因- latch.count=0
实例代码:
运行结果:
通过分析执行结果,发现每个线程的终止方式都如预料的那样。
await():等待count减少至0,或者被中断。
await(timeout,TimeUnit):等待count减少至0,或者超时,或者被中断。
countDown():count值减1。
本章主要对CountDownLatch的基本方法进行学习。
有关CountDownLatch的应用实例详见下一章:《Java并发:31》
1.CountDownLatch简介
CountDownLatch,是JDK1.5的java.util.concurrent并发包中提供的一个并发工具类。所谓CountDown即 倒计时 的意思,所谓Latch即 门闩 的意思。
所以综合起来,CountDownLatch指的就是 倒计时门闩,虽然这个叫法很奇怪,但是确能很好地表示它的作用。
其作用在JDK注释中是这样描述的:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
简单来说,CountDownLatch就是一种同步辅助工具类,这个工具类实现的效果是:
让一个或多个线程持续等待,直到其他多线程执行的一组操作全部完成以后,这些等待的线程才会继续执行。
2.CountDownLatch原理浅谈
下面简单介绍一些CountDownLatch的实现原理。引用[July 18, 2013 by Lokesh Gupta]的一段话和图:
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。
每当一个线程完成了自己的任务后,计数器的值就会减1。
当计数器值到达0时,它表示所有的线程已经完成了任务,然后在等待的线程就可以恢复执行任务。
3.CountDownLatch基本方法
CountDownLatch的主要方法很简单,如下:getCount():获取当前count的值。
wait():让当前线程在此CountDownLatch对象上等待,可以中断。与notify()、notifyAll()方法对应。
await():让当前线程等待此CountDownLatch对象的count变为0,可以中断。
await(timeout,TimeUnit):让当前线程等待此CountDownLatch对象的count变为0,可以超时、可以中断。
countDown():使此CountDownLatch对象的count值减1(无论执行多少次,count最小值为0)。
注意:
wait()是从Object类继承来的,关于它的用法,请参加《Java并发07》,这里不再赘述。
无论执行多少次countDown(),count最小值为0,不会变成负数。
4.基本方法练习
场景说明:练习目的:熟悉await():、await(timeout,TimeUnit):和countDown():的基本用法。
共计编写5个线程:
thread-0 : 等待方法-await(),终止原因-latch.count=0
thread-1 : 等待方法-await(),终止原因-thread.interrupt()
thread-2 : 等待方法-await(timeout,TimeUnit),终止原因- await timeout
thread-3 : 等待方法-await(timeout,TimeUnit),终止原因- thread.interrupt()
thread-4 : 等待方法-await(timeout,TimeUnit),终止原因- latch.count=0
实例代码:
//await()/await(timeout,TimeUnit) 与countDown() /** * 线程 等待方法 终止原因 * ------------------------------------------------ * thread-0 await() count=0 * thread-1 await() interrupted * ------------------------------------------------ * thread-2 await(timeout,TimeUnit) timeout * thread-3 await(timeout,TimeUnit) interrupted * thread-4 await(timeout,TimeUnit) count=0 */ System.out.println(); CountDownLatch latch = new CountDownLatch(num); //await() 直至latch 的count = 0 new Thread(() -> { LOGGER.info(Thread.currentThread().getName() + "(await0) is awaiting...."); try { latch.await(); LOGGER.info(Thread.currentThread().getName() + "(await0) is terminated because the latch's count is zero."); } catch (InterruptedException e) { LOGGER.info(Thread.currentThread().getName() + "(await0) is interrupted."); //e.printStackTrace(); } }).start(); //await() 被中断 Thread thread = new Thread(() -> { LOGGER.info(Thread.currentThread().getName() + "(await1) is awaiting...."); try { latch.await(); LOGGER.info(Thread.currentThread().getName() + "(await1) is terminated because the latch's count is zero."); } catch (InterruptedException e) { LOGGER.info(Thread.currentThread().getName() + "(await1) is terminated because it is interrupted."); //e.printStackTrace(); } }); thread.start(); //await(timeout,TimeUnit) //await(timeout,TimeUnit) timeout new Thread(() -> { LOGGER.info(Thread.currentThread().getName() + "(await2) is awaiting...."); try { //等待2秒 boolean result = latch.await(1, TimeUnit.SECONDS); //如果等到了count=0,则返回true,并停止等待 if (result) {//如果返回结果为true,表示在等待时间耗尽之前等到了count=0 LOGGER.info(Thread.currentThread().getName() + "(await2) is terminated because the latch's count is zero."); } else {//如果返回结果为false,表示等待时间耗尽,也没有等到count=0 LOGGER.info(Thread.currentThread().getName() + "(await2) is terminated because the the waiting time is timeout."); } } catch (InterruptedException e) { LOGGER.info(Thread.currentThread().getName() + "(await2) is terminated because it is interrupted."); //e.printStackTrace(); } }).start(); //await(timeout,TimeUnit) Thread thread1 = new Thread(() -> { LOGGER.info(Thread.currentThread().getName() + "(await3) is awaiting...."); try { //等待3秒 boolean result = latch.await(5, TimeUnit.SECONDS); //如果等到了count=0,则返回true,并停止等待 if (result) {//如果返回结果为true,表示在等待时间耗尽之前等到了count=0 LOGGER.info(Thread.currentThread().getName() + "(await3) is terminated because the latch's count is zero."); } else {//如果返回结果为false,表示等待时间耗尽,也没有等到count=0 LOGGER.info(Thread.currentThread().getName() + "(await3) is terminated because the the waiting time is timeout."); } } catch (InterruptedException e) { LOGGER.info(Thread.currentThread().getName() + "(await3) is terminated because it is interrupted."); //e.printStackTrace(); } }); thread1.start(); //await(timeout,TimeUnit) count=0 new Thread(() -> { LOGGER.info(Thread.currentThread().getName() + "(await4) is awaiting...."); try { //等待3秒 boolean result = latch.await(5, TimeUnit.SECONDS); //如果等到了count=0,则返回true,并停止等待 if (result) {//如果返回结果为true,表示在等待时间耗尽之前等到了count=0 LOGGER.info(Thread.currentThread().getName() + "(await4) is terminated because the latch's count is zero."); } else {//如果返回结果为false,表示等待时间耗尽,也没有等到count=0 LOGGER.info(Thread.currentThread().getName() + "(await4) is terminated because the the waiting time is timeout."); } } catch (InterruptedException e) { LOGGER.info(Thread.currentThread().getName() + "(await4) is interrupted."); //e.printStackTrace(); } }).start(); Thread.sleep(500); System.out.println(); //等待4秒 Thread.sleep(2000); System.out.println(); //中断 thread.interrupt(); thread1.interrupt(); Thread.sleep(1000); System.out.println(); //进行自减,直到count=0 while (latch.getCount() > 0) { //LOGGER.info(Thread.currentThread().getName() + " latch.countDown , count = " + latch.getCount()); latch.countDown(); }
运行结果:
2018-03-31 22:08:56 INFO CountDownLatchBasic:56 - Thread-0(await0) is awaiting.... 2018-03-31 22:08:56 INFO CountDownLatchBasic:117 - Thread-4(await4) is awaiting.... 2018-03-31 22:08:56 INFO CountDownLatchBasic:99 - Thread-3(await3) is awaiting.... 2018-03-31 22:08:56 INFO CountDownLatchBasic:81 - Thread-2(await2) is awaiting.... 2018-03-31 22:08:56 INFO CountDownLatchBasic:67 - Thread-1(await1) is awaiting.... 2018-03-31 22:08:57 INFO CountDownLatchBasic:89 - Thread-2(await2) is terminated because the the waiting time is timeout. 2018-03-31 22:08:58 INFO CountDownLatchBasic:110 - Thread-3(await3) is terminated because it is interrupted. 2018-03-31 22:08:58 INFO CountDownLatchBasic:72 - Thread-1(await1) is terminated because it is interrupted. 2018-03-31 22:08:59 INFO CountDownLatchBasic:59 - Thread-0(await0) is terminated because the latch's count is zero. 2018-03-31 22:08:59 INFO CountDownLatchBasic:123 - Thread-4(await4) is terminated because the latch's count is zero.
通过分析执行结果,发现每个线程的终止方式都如预料的那样。
5.重点总结
对CountDownLatch的重点方法进行总结:await():等待count减少至0,或者被中断。
await(timeout,TimeUnit):等待count减少至0,或者超时,或者被中断。
countDown():count值减1。
相关文章推荐
- Java并发21:Lock系列-ReadWriteLock接口和ReentrantReadWriteLock类基本方法学习实例
- Java并发28:ThreadLocal学习笔记-简介、基本方法及应用场景
- Java并发编程深入学习——CountDownLatch、CyclicBarrier和Semaphore
- Java并发19:Lock系列-Lock接口基本方法学习实例
- Java中CountDownLatch、CyclicBarrier、Thread.join方法基本应用
- Java 并发编程实战学习笔记——CountDownLatch的使用
- Java并发之CountDownLatch的学习
- Java并发20:Lock系列-Condition接口基本方法学习实例
- java并发学习之CountDownLatch
- [置顶] java 并发编程实战书籍学习 第五章,CountDownLatch,FutureTask,CyclicBarrier,Semaphore学习
- 《Java 7 并发编程指南》学习概要 (3)Semaphore, CountDownLatch, CyclicBarrier , Phaser, Exchanger
- Java并发学习之十七——线程同步工具之CountDownLatch
- 深入学习java并发编程:CountDownLatch、CyclicBarrier
- Java并发学习笔记(14) 闭锁(CountDownLatch)
- 关于高并发的几个基本锁的学习ReentrantLock,CountDownLatch ,CyclicBarrier,Semaphore,reentrantReadWriteLock
- Java并发学习之十一——同步方法
- Java并发之CountDownLatch、CyclicBarrier、Semaphore
- Java 并发专题 :闭锁 CountDownLatch 之一家人一起吃个饭
- Java线程(十一):CountDownLatch-线程并发的发令枪
- java并发包里的CountDownLatch的用法