2.8.等待多个并发完成

来源:互联网 发布:淘宝双十一抽奖在哪里 编辑:程序博客网 时间:2024/05/27 14:12

等待多个并发完成

经常会有这种场景:在主线程中启动多个工作线程,然后主线程需要等待工作线程全部完成后再进行下一步处理。如何实现等待多个线程完成?用Thread.join方法?这种方式耦合性太强,而且太土了!Java5引入了新的机制,这个机制语义明确、功能强大、使用灵活,这就是CountDownLatch类。

CountDownLatch类是同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许线程一致等待。这个类的构造函数需要传入一个整数,这个整数就是要等待完成操作的数目。一个线程要等待某些操作现执行完时,需要调用await()方法,这个方法让线程进入休眠直到等待的所有操作完成。当某一个操作完成后,它将调用countDown()方法将CountDownLatch的内部计数器减1。当计数器变成0的时候,CountDownLatch将唤醒所有调用await()方法而进入休眠的线程。

CountDownLatch和其他同步方法不同,它不是用来保护共享资源或者临界区的,而是用来同步执行多个任务的线程。CountDownLatch只准许进入一次,一旦内部计数器为0后,再调用方法将不起作用。

下面一个参加会议的例子说明CountDownLatch的作用和用法。主线程发起多个参会者,每个参会者都是一个线程,主线程需要等到所有参会者都到达之后才能开始会议。示例代码如下:


public class CountDownLatchDemo {    public static void main(String[] args){        CountDownLatch latch = new CountDownLatch(10);        Thread mettingThread = new Thread(new Metting(latch));        Thread[] assigneerThreads = new Thread[10];        Assigneer assigneer = new Assigneer(latch) ;        for(int i=0; i<latch.getCount(); i++){            Thread t = new Thread(assigneer);            assigneerThreads[i] = t;        }        System.out.println("main:启动会议线程");        mettingThread.start();        System.out.println("main:启动参会线程");        for(int i=0; i<assigneerThreads.length; i++){            assigneerThreads[i].start();        }        //等待参会线程结束        try {            latch.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("main:退出");    }}/** 参会线程**/class Assigneer implements Runnable{    private CountDownLatch latch ;    Assigneer(CountDownLatch latch) {        this.latch = latch;    }    @Override    public void run() {        System.out.println("参会线程:参会者:" + Thread.currentThread().getName() + "。参加会议....");        long delay = (long)(Math.random()*1000);        try {            Thread.sleep(delay);        } catch (InterruptedException e) {            e.printStackTrace();        }        this.latch.countDown();    }}/** 会议线程**/class Metting implements Runnable{    private CountDownLatch latch ;    Metting(CountDownLatch latch){        this.latch = latch;    }    @Override    public void run() {        System.out.println("会议线程:参会者数:" + this.latch.getCount() + "。等待参会者....");        try {            latch.await();            System.out.println("会议线程:参会者全部到达,开始会议...");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}


程序运行日志:

main:启动会议线程main:启动参会线程会议线程:参会者数:10。等待参会者....参会线程:参会者:Thread-1。参加会议....参会线程:参会者:Thread-3。参加会议....参会线程:参会者:Thread-2。参加会议....参会线程:参会者:Thread-4。参加会议....参会线程:参会者:Thread-5。参加会议....参会线程:参会者:Thread-6。参加会议....参会线程:参会者:Thread-8。参加会议....参会线程:参会者:Thread-7。参加会议....参会线程:参会者:Thread-9。参加会议....参会线程:参会者:Thread-10。参加会议....会议线程:参会者全部到达,开始会议...main:退出


0 0
原创粉丝点击