CountDownLatch允许一个或多个线程等待其他线程完成操作。
CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待n个节点完成,就传入n。
注意:CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部的计数器的值
简单示例:
1 class CountDownLatchTest{ 2 static CountDownLatch c = new CountDownLatch(2); 3 public static void main(String[] args) throws InterruptedException{ 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 System.out.println(1); 8 c.countDown(); 9 System.out.println(2); 10 c.countDown();//计数器减一 11 } 12 }).start(); 13 c.await();////只要计数器为0,那么线程就可以结束阻塞往下执行,进而保证线程同时开始 14 System.out.println("3"); 15 } 16 }
复杂示例:
1 /* 2 测试,客户端模拟ConnectionRunner获取、使用、释放连接的过程 3 */ 4 class ConnectionPoolTest{ 5 static ConnectionPool pool = new ConnectionPool(10); 6 //保证所有的ConnectionRunner能同时开始 7 static CountDownLatch start = new CountDownLatch(1); 8 //main线程将会等待所有ConnectionRunner结束后才能继续执行 9 static CountDownLatch end; 10 public static void main(String[] args) throws Exception{ 11 //线程数量,可以修改线程数量进行观察 12 int threadCount = 20; 13 end = new CountDownLatch(threadCount); 14 int count = 20; 15 AtomicInteger got = new AtomicInteger(); 16 AtomicInteger notGot = new AtomicInteger(); 17 for (int i = 0; i < threadCount; i++){ 18 Thread thread = new Thread(new ConnectionRunner(count, got, notGot), "ConnectionRunnerThread"); 19 thread.start(); 20 } 21 start.countDown();//只要计数器为0,那么线程就可以结束阻塞往下执行,进而保证线程同时开始 22 end.await(); 23 System.out.println("total invoke: " + (threadCount * count)); 24 System.out.println("got connection: " + got); 25 System.out.println("not got connection: " + notGot); 26 } 27 28 static class ConnectionRunner implements Runnable{ 29 int count; 30 AtomicInteger got; 31 AtomicInteger notGot; 32 public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot){ 33 this.count = count; 34 this.got = got; 35 this.notGot = notGot; 36 } 37 @Override 38 public void run(){ 39 try{ 40 start.await(); 41 }catch (Exception ex){ 42 } 43 while (count > 0){ 44 try { 45 //从线程池中获取连接,如果1000ms内无法获取到,将会返回null 46 //分别统计连接获取的数量got和未获取到的数量notGot 47 Connection connection = pool.fetchConnection(1000); 48 if (connection != null){ 49 try { 50 connection.createStatement();//创建一个 Statement 对象来将 SQL 语句发送到数据库 51 connection.commit();// 使所有上一次提交/回滚后进行的更改成为持久更改, 52 // 并释放此 Connection 对象当前持有的所有数据库锁。 53 }finally { 54 pool.releaseConnection(connection); 55 got.getAndIncrement(); 56 } 57 }else { 58 notGot.getAndIncrement(); 59 } 60 }catch (Exception ex){ 61 }finally { 62 count--; 63 } 64 } 65 end.countDown(); 66 } 67 } 68 }