java - Java中的生产者/消费者模式

标签 java concurrency parallel-processing consumer producer

我正在考虑如何在Java中实现生产者/消费者模式。

假设我有 3 个线程和一个包含任务的列表(假设大约有 5 个任务)。每个线程从列表中获取任务并并发执行。我当前的方法是使用 CountDownLatch

int N = 3;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
ConcurrentLinkedQueue<String> tasks = new ConcurrentLinkedQueue<String>();

main() {
    for (int i=0;i<N;i++) {
        new Thread(new Worker()).start();
    }
    startSignal.countDown();
    doneSignal.await();
    System.out.println("done");
}

class Worker implements Runnable {
    public void run() {
        startSignal.await();
            while ((s = tasks.poll()) != null) {
                // do lengthy task here
                if (task failed) {
                    tasks.add(s);
                    return; // assume that task fails badly and have to stop the thread
                }
            }
        doneSignal.countDown();
    }
}

我想要实现的是,如果一个线程在处理任务时失败,它将被添加回任务列表中,以便由当前或任何其他线程再次拾取,但根据我当前使用 CountDownLatch 的方法,显然它是不可能这样做,因为调用 didSignal.countDown() 后,线程假设它已经完成了任务。

对于这种情况,最好的方法是什么?使用 Executor 是唯一的方法吗?

最佳答案

我想说,对于这种情况,这是一个过于复杂(并且容易出错)的解决方案,使用通用的 BlockingQueue(从该阻塞队列进行轮询并将作业移交给 ExecutorService 的单线程)确实会更简单。

在这种情况下看不出您需要 CountDownLatch 的任何原因,它只是不必要地使您的工作人员变得复杂,它必须了解它正在线程环境中运行,并且还必须在完成时清理所有脏东西。 BlockingQueues 和 ExecutorServices 正是为了让您摆脱这些问题。

关于java - Java中的生产者/消费者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7061562/

相关文章:

java - dalvik.system.PathClassLoader 无法转换为 java.net.URLClassLoader

java - 发生在 Java 内存模型之前和程序顺序

python - 为具有多个输入和输出的函数并行化 for 循环

java - 无法设置我的 RecyclerView 以显示来自 API 回调的完整数据

Java 是否支持默认的参数值

swift - 如何防御性地创建 Rx Observables 并避免竞争条件?

perl - 如何在 Perl 中测试对资源(缓存)的并发访问?

.net-4.0 - 对于此代码,为什么 PLINQ 比 LINQ 慢?

C++ Intel TBB和Microsoft PPL,如何在并行循环中使用next_permutation?

java - Tomcat server.xml 中的调试级别 (0-99) 如何影响速度?