一.CountDownLatch介绍

  1. CountDownLatchJDK1.5之后引入的,存在于java.util.concurrent包下,能够使一个线程等待其他线程完成动作后再执行。
    构造方法:
  1. public CountDownLatch(int count) {
  2. if (count < 0) throw new IllegalArgumentException("count < 0");
  3. this.sync = new Sync(count);
  4. }

主要方法:

countDown()方法每调用一次,计数器减1

await()方法使当前线程处于阻塞状态,知道计数器值为0

二.CountDownLatch使用

  1. package com;
  2.  
  3. import java.util.*;
  4. import java.util.concurrent.ConcurrentHashMap;
  5. import java.util.concurrent.ConcurrentMap;
  6. import java.util.concurrent.CountDownLatch;
  7. import java.util.concurrent.atomic.AtomicInteger;
  8.  
  9. /**
  10. * CountDownLatch测试
  11. */
  12. class myThread<T> extends Thread {
  13. CountDownLatch countDownLatch;
  14. Map map;
  15. //构造函数,传入的是Map
  16. public myThread(CountDownLatch countDownLatch, Map map) {
  17. this.countDownLatch = countDownLatch;
  18. this.map = map;
  19. }
  20. public void run() {
  21. map.put(Thread.currentThread().getName(),new Object());
  22. countDownLatch.countDown();//线程执行一次就countDown计数器减少1
  23. }
  24. }
  25.  
  26. public class TestThreadAndCollection {
  27. public static void main(String[] args) throws InterruptedException {
  28. //表示测试100次
  29. for (int i = 0; i < 100; i++) {
  30. test();
  31. }
  32. }
  33.  
  34. public static void test() throws InterruptedException {
  35. CountDownLatch latch = new CountDownLatch(2000);
  36. //使用HashMap,这是线程不安全的
  37. Map<String ,Object> hashMap = new HashMap();
  38. //使用ConcurrentHashMap,线程安全的
  39. //Map<String ,Object> concurrentHashMap = new ConcurrentHashMap();
  40. //两个for循环,2000个线程
  41. for (int i = 0; i < 1000; i++) {
  42. //多线程HashMap测试
  43. //myThread mThread = new myThread(latch, hashMap);
  44. //多线程concurrentHashMap测试
  45. myThread mThread = new myThread(latch, hashMap);
  46. mThread.start();
  47. }
  48. for (int i = 0; i < 1000; i++) {
  49. myThread mThread = new myThread(latch, hashMap);
  50. mThread.start();
  51. }
  52. //等待当前所有子线程执行完,这里也就是使main线程处于等待状态,完了后再输出大小
  53. latch.await();
  54. //这里是main线程sleep一段时间(1秒),效果同latch.await();
  55. /* try{
  56. System.out.println(Thread.currentThread().getName());//当前线程输出的是main
  57. Thread.sleep(1000);
  58. }catch(InterruptedException e){
  59. e.printStackTrace();
  60. }*/
  61. //System.out.println(concurrentHashMap.size());
  62. System.out.println(hashMap.size());
  63. }
  64. }

因为多线程下HashMap是不安全的,所以结果:

而ConcurrentHashMap是线程安全的,结果如下图:

ConcurrentHashMap下,如果把CountDownLatch latch = new CountDownLatch(2000);中参数2000改成小于2000的值(1000)那么输出的结果如下:

因为countDown()计数器递减为0的时候,await()方法就不会再阻塞main线程,所以输出语句的执行可能会在所有线程put完成之前,因此结果不是2000

CountDownLatch在多线程程序中的应用的更多相关文章

  1. zz剖析为什么在多核多线程程序中要慎用volatile关键字?

    [摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...

  2. 多线程程序中fork导致的一些问题

    最近项目中,在使用多线程和多进程时,遇到了些问题. 问题描述:在多线程程序中fork出一个新进程,发现新的进程无法正常工作. 解决办法:将开线程的代码放在fork以后.也就是放在新的子进程中进行创建. ...

  3. Linux -- 在多线程程序中避免False Sharing

    1.什么是false sharing 在对称多处理器(SMP)系统中,每个处理器均有属于自己的本地高速缓存区. 如图,CPU0和CPU1有各自的本地高速缓存区(cache).线程0和线程1会用到不同的 ...

  4. gdb常用命令及使用gdb调试多进程多线程程序

    一.常用普通调试命令 1.简单介绍GDB 介绍: gdb是Linux环境下的代码调试⼯具.使⽤:需要在源代码⽣成的时候加上 -g 选项.开始使⽤: gdb binFile退出: ctrl + d 或 ...

  5. 《Java大学教程》—第22章 多线程程序

    22.2 进程(process):P551时间切片(time-slicing):处理器只是完成了一个任务的一部分工作,然后完成下一个任务的一部分工作,因为处理吕每次完成工作的时间都非常短,因此看起来这 ...

  6. Linux下多线程编程中信号量介绍及简单使用

    在Linux中有两种方法用于处理线程同步:信号量和互斥量. 线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保 ...

  7. C# 多线程程序隐患

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. 在 java 程序中怎么保证多线程的运行安全?(未完成)

    在 java 程序中怎么保证多线程的运行安全?(未完成)

  9. java程序中的多线程(转)

    为什么会排队等待? 下面的这个简单的 Java 程序完成四项不相关的任务.这样的程序有单个控制线程,控制在这四个任务之间线性地移动.此外,因为所需的资源 ― 打印机.磁盘.数据库和显示屏 -- 由于硬 ...

随机推荐

  1. VPC配置介绍

    VPC(Virtual Port-Channel)是Cisco Nexus系列交换机中的一个特性.它支持一个跨机箱的二层Port-Channel.对于第三方设备来说(交换机或服务器)物理上是连接到了两 ...

  2. 部署--云服务器(RubyChina上的转帖); 附加用cap部署sidekiq

    https://ruby-china.org/topics/36899 附加https://ruby-china.org/topics/36899 Capistrano + Rails5.2部署 使用 ...

  3. sgu 139 Help Needed!

    题意:16数码是否有解? 先计算展开成一维后逆序对.如果0在最后一行,那么逆序偶时有解.4*4时(n为偶)0的位置上升一行,逆序对+3或-1(奇偶性变化).(n为奇时+2或+0,不变) #includ ...

  4. android -------- 安装APK报错:Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE解决方法

    记录一个 DELETE_FAILED_INTERNAL_ERROR Error while Installing APK问题 之前遇到这个问题 方案1 将data/data/目录下该应用的包名的目录删 ...

  5. re正则表达式方法

    目录 1.python正则匹配 1.1 re.search 正则表达式 1.2 re.match() 正则表达式 1.3 re.match与re.search的区别 1.4 检索和替换 1.5 正则表 ...

  6. 创建xml树

    XMLElement 节点XMLDocument 节点的CUID操作 XMLNode 抽象类 操作节点 (XMLElement XMLDocument ) XElement xElement = ne ...

  7. 函数使用六:ABAP4_CALL_TRANSACTION

    此函数是在程序中调用一个事物代码,跳转或者执行事物代码的程序. 参数说明: Import TCODE                            执行的事物代码 SKIP_SCREEN   ...

  8. 【LeetCode】二分查找

    给一个升序数组,找到目标值在数组中的起始和结束位置,时间复杂度为 O(log n). e.g. 给定数组 [5, 7, 7, 8, 8, 10] 和目标值 8,返回 [3, 4].若目标值不在数组中, ...

  9. js 获取数组重复的元素

    //获取数组重复的元素 function refrain(arr) { var tmp = []; if(Array.isArray(arr)) { arr.concat().sort().sort( ...

  10. vsftpd更新和修改版本号教程

    1.rpm包更新 类似以下更新即可 rpm -Uvh vsftpd--.el6.x86_64.rpm 2.源码更新 不懂为什么对于新版本可能只有源码包而没有rpm等包,如此只能以源码更新了. .tar ...