CountDownLatch在多线程程序中的应用
一.CountDownLatch介绍
CountDownLatch是JDK1.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