Java多线程中如何使用CountDownLatch?

210
我可以帮助您理解Java中的CountDownLatch是什么以及何时使用它。这个程序的工作原理并不是很清楚。据我所知,所有三个线程同时启动,每个线程都会在3000毫秒后调用CountDownLatch。因此,倒数会逐个递减。当闩锁变为零时,程序将打印“已完成”。也许我理解的方式是不正确的。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class Processor implements Runnable {
    private CountDownLatch latch;

    public Processor(CountDownLatch latch) {
        this.latch = latch;
    }

    public void run() {
        System.out.println("Started.");

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        latch.countDown();
    }
}

抱歉,我只能使用英文回答您的问题。
public class App {

    public static void main(String[] args) {

        CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0

        ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool

        for(int i=0; i < 3; i++) {
            executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
        }

        try {
            latch.await();  // wait until latch counted down to 0
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Completed.");
    }

}

2
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html - Christophe Roussy
12
我刚刚使用了你的问题示例代码来进行安卓平行服务批处理,效果非常好。非常感谢! - Roisgoen
1
从2012年的这个视频中来到这里,它展示了与此处示例的_惊人相似之处_。 对于任何感兴趣的人,这是一个名叫John的人制作的Java多线程教程系列的一部分。我喜欢John。强烈推荐。 - Elia Grady
13个回答

2
package practice;

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch c= new CountDownLatch(3);  // need to decrements the count (3) to zero by calling countDown() method so that main thread will wake up after calling await() method 
        Task t = new Task(c);
        Task t1 = new Task(c);
        Task t2 = new Task(c);
        t.start();
        t1.start();
        t2.start();
        c.await(); // when count becomes zero main thread will wake up 
        System.out.println("This will print after count down latch count become zero");
    }
}

class Task extends Thread{
    CountDownLatch c;

    public Task(CountDownLatch c) {
        this.c = c;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(1000);
            c.countDown();   // each thread decrement the count by one 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

0

最好的选择是CyclicBarrier,根据https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html 请参考:

CountDownLatch是使用给定的计数进行初始化的。await方法会阻塞,直到当前计数由于调用countDown()方法而达到零,此后所有等待的线程都会被释放,并且任何随后的await调用都会立即返回。这是一个一次性的现象--计数无法重置。如果您需要一个可以重置计数的版本,请考虑使用CyclicBarrier。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接