concurrent包里的CountDownLatch
CountDownLatch是一个非常实用的多线程控制工具类
CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量.每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了
常用方法
//构造方法,创建一个值为count 的计数器。 public CountDownLatch(int count) { }; //阻塞当前线程,将当前线程加入阻塞队列。 public void await() throws InterruptedException { }; //在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行, public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。 public void countDown() { };
eg:
(1)计数器为2,有2个子线程来完成子任务,主线程等待5子线程执行完才继续执行
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchDemo{ private static CountDownLatch cdl = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException { System.out.println("主线程开始执行…"); //第一个子线程执行 ExecutorService es1 = Executors.newSingleThreadExecutor(); es1.execute(new Runnable() { @Override public void run() { try { Thread.sleep(1000); System.out.println("子线程:"+Thread.currentThread().getName()+"执行"); } catch (InterruptedException e) { e.printStackTrace(); } cdl.countDown(); } }); es1.shutdown(); //第二个子线程执行 ExecutorService es2 = Executors.newSingleThreadExecutor(); es2.execute(new Runnable() { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("子线程:"+Thread.currentThread().getName()+"执行"); cdl.countDown(); } }); es2.shutdown(); System.out.println("等待两个线程执行完毕…"); try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("两个子线程都执行完毕,继续执行主线程"); } }
输出
主线程开始执行
等待两个线程执行完毕
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程
(2)计数器为5,有5个线程来完成任务,主线程等待5线程执行完才继续执行
import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchDemo implements Runnable{ private static CountDownLatch cdl = new CountDownLatch(5); private static CountDownLatchDemo demo = new CountDownLatchDemo(); @Override public void run() { try { Thread.sleep(new Random().nextInt(10) * 1000); System.out.println(Thread.currentThread().getName()+" check"); } catch (InterruptedException e) { e.printStackTrace(); } finally { //计数减一 cdl.countDown(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(5); for (int i=0; i<5; i++){ exec.submit(demo); } // 等待 cdl.await(); System.out.println("end!"); // 关闭线程池 exec.shutdown(); } }
输出:
pool-1-thread-1 check
pool-1-thread-3 check
pool-1-thread-2 check
pool-1-thread-5 check
pool-1-thread-4 check
end!