Java 使用ExecutorService的管道模式中的多线程阶段

Java 使用ExecutorService的管道模式中的多线程阶段,java,multithreading,design-patterns,pipeline,executorservice,Java,Multithreading,Design Patterns,Pipeline,Executorservice,我有一个多级管道。每个阶段在单独的线程中运行,使用有界阻塞阵列队列进行通信。我试图在最慢的阶段使用多线程来提高吞吐量 问题:这方面的建议实施方式是什么?是否有一个库可以使这个实现更简单、更容易阅读 输入队列->阶段1 4线程->有界队列->阶段2 要求: 输入队列上的工作单元是独立的 工作单元是严格有序的——输出的顺序应该与输入的顺序相同 必须对阶段1进行节流-如果输出超过一定大小,则必须停止 阶段1中的异常将导致输出队列中出现毒药并终止ExecutorService。应尽最大努力放弃排队的任务

我有一个多级管道。每个阶段在单独的线程中运行,使用有界阻塞阵列队列进行通信。我试图在最慢的阶段使用多线程来提高吞吐量

问题:这方面的建议实施方式是什么?是否有一个库可以使这个实现更简单、更容易阅读

输入队列->阶段1 4线程->有界队列->阶段2

要求:

输入队列上的工作单元是独立的

工作单元是严格有序的——输出的顺序应该与输入的顺序相同

必须对阶段1进行节流-如果输出超过一定大小,则必须停止

阶段1中的异常将导致输出队列中出现毒药并终止ExecutorService。应尽最大努力放弃排队的任务

**我提议的执行:**

我正在考虑使用一个线程池执行器,线程数量有限

在每个工作单元上,将通过倒计时闩锁强制执行严格的命令。只有当前一个工作单元的闩锁为0且队列中有空间时,线程才能推送结果。这还考虑了节流,因为线程将阻塞,直到输出队列上有空间为止

class WorkUnit {
   CountDownLatch previousLatch;
   CountDownLatch myLatch;
}

class MyRunnable extends Runnable {
   public void run() {
       //do work...
       previousLatch.await();
       ouputQueue.put( result );
       myLatch.countDown();
   }
}
异常处理是我有点困惑的地方。我正在考虑压倒一切 ThreadPoolExecutor.afterExecute,如果出现异常,它将调用shutdownNow

class MyThreadPoolExecutor extends ThreadPoolExecutor {
      protected void afterExecute(Runnable r, Throwable t) {
           if(t != null) {
               //record exection, log, alert, etc
               ouput.put(POISON_PILL);
               shutdownNow();
           }
      }
}

使用ExecutorService需要完全异步的设计,而不使用诸如CountDownLatch.countDown或BlockingQueue.take之类的阻塞操作。当操作B必须等待某些事件时,该事件应通过向ExecutorService提交Runnable来启动操作B

在这种情况下,您应该创建自定义类而不是队列。这些类应该接受消息并在内部存储它们,或者根据一些规则提交实现Stage1或Stage2的任务,例如限制正在运行的Stage1任务的数量


至于订购,请用序列号替换对上一个任务的引用。

我将在每个阶段使用ExecutorService。我会设计它,使线程池一直运行,而不是关闭。@foampile我的问题是什么是这个问题的最佳解决方案…是否有一个设计模式、库等,可以干净地实现我所看到的内存泄漏:字段CountDownLatch previousslatch;将所有工作单元编织在一个链接列表中,这样它们就不会被垃圾收集;将阻止工作线程进行有用的工作。实际上,从有界队列中提取时需要保持秩序,而不是插入时。@AlexeiKaigorodov非常有效的点,尤其是re。内存泄漏。通过在等待后设置previousLatch=null,可以修复内存泄漏。轻微的性能下降是一个问题,但我愿意为此付出代价,以获得严格的订购。关于正确实施这一点,您有什么建议?