`
gaoyuntao2005
  • 浏览: 312274 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发学习之一:CountDownLatch

阅读更多

看了几个月的《Java Concurrency in Practice》到了今天终于算可以收尾了,之前留下的看不懂的代码,现在也基本明晰了一些 

全书介绍了很多细节问题,很多注意的点,很多原则性问题,个人感觉,无论看几遍,都是值得的。但很多都是一些需要去记忆的东西,这个是需要经验的积累的。 
真正想在思考上,在设计上得到更大的提高,看来必然是要落在了concurrent包的数个同步器的实现的分析和对AQS的理解上了 

同步器是针对一些通用的场景设计的,由Doug Lea实现的,换句话来说,其实从同步器可以看出常用的一些需求,既然有了需求,又学会了工具(AQS框架)的使用,就可以按照自己的思维,试着重新去实现一下了 


CountDownLatch 

CountDownLatch是针对这样一个需求设计的:n个参与者需要进行一件事情(比如开会),只有当他们都到了,才能正式开始,所以先到的需要等,并且同时开始 

首先,先用点“拙劣”的工具(1.5之前的实现方法)试着写一下实现 

Java代码  收藏代码
  1. public class TestOfCountDownLatches {  
  2.       
  3.     int count;  
  4.       
  5.     Object lock = new Object();  
  6.       
  7.     public TestOfCountDownLatches(int count)  
  8.     {  
  9.         this.count = count;  
  10.     }  
  11.       
  12.     public void countDown()  
  13.     {  
  14.         synchronized(lock)  
  15.         {  
  16.             count--;  
  17.             if(count == 0)  
  18.             {  
  19.                 lock.notifyAll();  
  20.             }  
  21.         }  
  22.     }  
  23.   
  24.         public void await() throws InterruptedException  
  25.     {  
  26.         synchronized(lock)  
  27.         {  
  28. //中间还出现了点小问题:没写if(count == 0),这就导致了如果主线程先执行了countdown,其他线程再执行await,就会无限制的等待着了,从这个小错误也学会了并发框架的一个原则:阻塞还是不阻塞,应该是严格依赖于状态(state)的,而与先后次序没关系  
  29.             if(count != 0)  
  30.                 lock.wait();  
  31.         }  
  32.     }  
  33. }  


测试方法: 
Java代码  收藏代码
  1. public long timeTasks1(int nThreads,final Runnable task)  
  2.         {  
  3.             final TestOfCountDownLatches endLatch = new TestOfCountDownLatches(nThreads);  
  4.             final TestOfCountDownLatches startLatch = new TestOfCountDownLatches(1);  
  5.             for(int i = 0;i<nThreads;i++)  
  6.             {  
  7.                 Thread t = new Thread(){  
  8.                     public void run() {  
  9.                         try {  
  10.                             startLatch.await();  
  11.                             try {  
  12.                                 task.run();  
  13.                             } finally {  
  14.                                 endLatch.countDown();  
  15.                             }  
  16.                         } catch (InterruptedException ignored) { }  
  17.                     }  
  18.                 };  
  19.                 t.start();  
  20.             }  
  21.             long start = System.nanoTime();           
  22.             try {  
  23.                 startLatch.countDown();  
  24.                 endLatch.await();  
  25.             } catch (InterruptedException e) {  
  26.                   
  27.             }  
  28.             long end = System.nanoTime();  
  29.             return end-start;  
  30.         }  


跑了一下,没啥问题,与CountDownLatches的功能基本一致的 

再看看CountDownLatches的实现(主要是看它的同步器) 
Java代码  收藏代码
  1. private static final class Sync extends AbstractQueuedSynchronizer {  
  2.         private static final long serialVersionUID = 4982264981922014374L;  
  3.   
  4.         Sync(int count) {  
  5.             setState(count);  
  6.         }  
  7.   
  8.         int getCount() {  
  9.             return getState();  
  10.         }  
  11. //被await()调用  
  12.         public int tryAcquireShared(int acquires) {  
  13.             return getState() == 01 : -1;  
  14.         }  
  15. //被countDown()调用  
  16.         public boolean tryReleaseShared(int releases) {  
  17.             // Decrement count; signal when transition to zero  
  18.             for (;;) {  
  19.                 int c = getState();  
  20.                 if (c == 0)  
  21.                     return false;  
  22.                 int nextc = c-1;  
  23.                 if (compareAndSetState(c, nextc))  
  24.                     return nextc == 0;  
  25.             }  
  26.         }  
  27.     }  


在实现原理上是一致的,await时比较一下state(相当于第一个版本的count),如果满足了,则不阻塞(返回1),如果不满足,阻塞(返回-1)(关于阻塞与否的代码都在AQS里面) 
在countDown时则进行一下--操作,如果满足0“return nextc == 0;”了,则释放阻塞 

既然主要目的是学习AQS,就debug了一下,尽量去了解AQS的实现原理 
主要了解到以下几个方面:(下面的描述只针对AQS的shared模式) 
1.AQS没用正常的wait,notifyAll,lock的阻塞等方法,而是用了一个LockSupport对象来支持类似操作,该对象的方法全是本地方法,相当于对synchronized和wait等操作用了一个统一的形式 
2.AQS中维持了一个等待队列,很奇特的是,该等待队列“完全没用锁”,比如说一个acquice操作,当没成功的时候,是需要将该线程进入等待队列的,多线程的访问,所以这个入队的过程应该要保证它的原子性 
但AQS没有这样做,它只用了一些非常高效的改变int型的原子方法(由Unsafe提供),针对每一个需要保证原子性的操作(如入队),它都用了一个while(true)这样的形式,一旦失败(比如发现队尾已经被别的线程改变了),则从新获取当前状态,重新入队,很神奇,很高效,同时也需要考虑得面面俱到的一个实现,在文章中称之为“非阻塞算法”,在后文会对该算法写一篇详细介绍 
虽然用1.5之前的wait等方法可以实现,但无疑用AQS这套框架会更高效,响应更快 

再贴一个使用CountDownLatches的例子做为结尾 
Java代码  收藏代码
  1. public long timeTasks2(int nThreads, final Runnable task)  
  2.                 throws InterruptedException {  
  3.             final CountDownLatch startGate = new CountDownLatch(1);  
  4.             final CountDownLatch endGate = new CountDownLatch(nThreads);  
  5.   
  6.             for (int i = 0; i < nThreads; i++) {  
  7.                 Thread t = new Thread() {  
  8.                     public void run() {  
  9.                         try {  
  10.                             startGate.await();  
  11.                             try {  
  12.                                 task.run();  
  13.                             } finally {  
  14.                                 endGate.countDown();  
  15.                             }  
  16.                         } catch (InterruptedException ignored) { }  
  17.                     }  
  18.                 };  
  19.                 t.start();  
  20.             }  
  21.   
  22.             long start = System.nanoTime();  
  23.             startGate.countDown();  
  24.             endGate.await();  
  25.             long end = System.nanoTime();  
  26.             return end-start;  
  27.         }  

分享到:
评论

相关推荐

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java 并发编程实战.pdf

    根据提供的信息,“Java 并发编程实战.pdf”这本书聚焦于Java并发编程的实践与应用,旨在帮助读者深入了解并掌握...无论是对于初学者还是有一定经验的开发者来说,《Java并发编程实战》都是一本值得深入学习的好书。

    Java 并发核心编程

    #### 一、Java并发概述 自Java诞生之初,其设计者就赋予了该语言强大的并发处理能力。Java语言内置了对线程和锁的支持,这使得开发者能够轻松地编写多线程应用程序。本文旨在帮助Java开发者深入理解并发的核心概念...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...

    Java并发编程:设计原则与模式(第二版)-3

    《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java多线程编程技术的权威著作。这本书详细阐述了在Java平台中进行高效并发处理的关键概念、设计原则和实用模式。以下是对该书内容的一些核心知识点的概述...

    java高并发编程第一版

    《Java高并发编程》第一版是一本专注于...通过阅读《Java高并发编程》第一版,开发者不仅可以掌握Java并发编程的核心概念和技术,还能了解到如何在实际工作中设计和实现高效、安全的并发程序,提升系统的并发处理能力。

    java 并发学习总结

    理解并熟练运用这些知识点,是成为一名合格的Java并发程序员的基础。在实际开发中,需要结合具体场景,选择合适的并发策略,以实现高性能、高并发的系统。通过不断实践和学习,可以进一步提升对Java并发编程的理解和...

    java并发编程与实践

    通过深入学习"Java并发编程与实践"文档,开发者能够提升自己在高并发环境下的编程能力,设计出更加健壮和高效的Java应用程序。这份资料对于理解Java并发原理、优化并发代码和解决并发问题具有极大的价值。

    java并发工具类(CountDownLatch+Semaphore+Exchanger)

    Java并发工具类是Java并发编程中的重要组成部分,其中包括了多种实用的工具,如CountDownLatch、Semaphore和Exchanger,这些工具类极大地简化了多线程环境下的同步和协调问题。 1. **CountDownLatch**: ...

    JAVA并发编程艺术pdf版

    《JAVA并发编程艺术》是Java开发者深入理解和掌握并发编程的一本重要著作,它涵盖了Java并发领域的核心概念和技术。这本书详细阐述了如何在多线程环境下有效地编写高效、可靠的代码,对于提升Java程序员的技能水平...

    Java并发程序设计教程

    7、并发流程控制手段:CountDownlatch、Barrier 8、定时器: ScheduledExecutorService、大规模定时器TimerWheel 9、并发三大定律:Amdahl、Gustafson、Sun-Ni 10、神人和图书 11、业界发展情况: GPGPU、OpenCL 12、...

    Java并发编程-3.pdf

    Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...

    Java并发编程实践高清pdf及源码

    《Java并发编程实践》是一本深入探讨Java多线程编程的经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和David Holmes等专家共同编写。这本书全面介绍了Java平台上的并发编程技术,是Java开发...

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 Java并发编程是Java语言中的一种高级技术,用于处理多线程编程中的同步问题。Java 1.5中引入了几个高效的辅助类,包括CountDownLatch、...

    Java并发编程学习笔记.rar

    这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...

    java高并发程序设计(原版电子书)

    《Java高并发程序设计》是一本深入探讨Java平台上的并发编程技术的专业书籍,由葛一鸣等人编著。这本书旨在帮助读者理解并掌握在高并发环境下编写高效、稳定且可扩展的Java应用程序的关键技巧和最佳实践。以下是该书...

    《java 并发编程实战高清PDF版》

    在Java并发编程中,多线程是核心概念之一。多线程允许程序同时执行多个任务,从而充分利用系统资源,提高程序性能。然而,多线程编程也带来了同步和竞态条件等问题,这需要开发者具备良好的线程管理和同步机制的知识...

    Java编程并发程序设计

    7、并发流程控制手段:CountDownlatch、Barrier 8、定时器: ScheduledExecutorService、大规模定时器TimerWheel 9、并发三大定律:Amdahl、Gustafson、Sun-Ni 10、神人和图书 11、业界发展情况: GPGPU、OpenCL 12、...

    java并发编程实战.zip

    《Java并发编程实战》这本书是Java开发者深入理解并发编程的重要参考资料。它涵盖了Java并发的核心概念、工具...通过学习书中的内容,开发者能够更好地理解和掌握Java并发编程,从而编写出更高效、更稳定的多线程程序。

Global site tag (gtag.js) - Google Analytics