我正在使用执行程序服务进行多线程处理。跨越15个线程,当前进程确实完成了15个线程,然后转移到下一个执行器服务,这些服务再次跨越15个线程。我正在寻找代码帮助,如果步骤1执行器服务中的任何当前线程完成处理,我需要继续下一个执行器服务,它可以开始使用线程而不是等待完成步骤1中的15个线程完成。
我想利用已完成的线程并继续执行第2步,即使其他线程在步骤1中执行,并且只要步骤1中的每个线程完成,步骤2就可以抓取并继续处理。建议请
// Step 1
ExecutorService executor1 = Executors.newFixedThreadPool(15);
for (int i=0;i<=15;i++) {
Runnable worker = new Runnable("Step 1 Insert");
executor1.execute(worker); }
executor1.shutdown();
// Step 2
ExecutorService executor2 = Executors.newFixedThreadPool(15);
for (int i=0;i<=15;i++) {
Runnable worker = new Runnable("Step 2 Insert");
executor2.execute(worker); }
executor2.shutdown();
答案 0 :(得分:0)
您可以使用ExecutorCompletionService。我稍微修改了JavaDoc的例子
ExecutorService executor1 = Executors.newFixedThreadPool(15);
ExecutorService executor2 = Executors.newFixedThreadPool(15);
....
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(executor1);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
executor2.submit(r);
}
executor1.shutdown();
//and shutdown executor2 when you don't need it
Result
类仅作为示例,我假设它实现了Callable
或Runnable
,因此可以将其提交到第二个执行程序中。
您还可以将ExecutorService
的实例初始化为new ThreadPoolExecutor(0, 15, 10, TimeUnit.SECONDS, new LinkedBlockingQueue())
来终止当前不需要的线程,但是您希望稍后重用此执行程序。
或者你可以简单地使用一个执行器。从ExecutorCompletionService
收到完成的任务后,将其(或其结果)重新提交到同一执行者(Thanks @Fildor)。但在这种情况下,您需要确定第一次完成任务的时间。
for (int i = 0; i < n;) {
Result r = ecs.take().get();
if (r != null && isCompletedFirstTime(r))//some user defined function
executor1.submit(r);
else
++i;//we need to know when to stop, otherwise we'll stuck in `take()`
}
答案 1 :(得分:0)
为什么不能在同一个Runnable中执行所有步骤? e.g。
var dateitems = JSON.stringify($jsonDateInit);
var select_items = JSON.stringify($jsonSelectInit);
答案 2 :(得分:0)
@ SpiderPig的答案是一个很好的解决方案恕我直言,但我想提供一个替代方案,以防你想要解耦步骤:
使用一个单独的Executor,在您的情况下,需求似乎是一个包含15个Threads的FixedThreadPool。
接下来将定义Step-Runnables,如下所示:
class StepX implements Runnable{
private final State _state; // Reference to the data to work on.
StepX( State state ){
_state = state;
}
public void run(){
// work on _state
executor.submit( new StepXplusOne( _state ) ); // reference executor in outer class and schedule next step.
}
}
您可以看到我使用了State
对象,该对象包含执行步骤和收集结果所需的所有数据。
当然,您需要将StepX定义为Step1,Step2,...
在外层课程中,你只需要提交N Step1-Runnables,它只会使用你的15个主题并完成这些步骤。
当我完成所有步骤时,我遗漏了一个发出信号的方法,因为有很多可能性,我相信你可以自己选择一个。
答案 3 :(得分:-1)
您可以尝试使用CountDownLatch类。
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html
final CountDownLatch latch = new CountDownLatch(1);
ExecutorService executor1 = Executors.newFixedThreadPool(15);
for (int i = 0; i <= 15; i++) {
Runnable worker = new Runnable() {
@Override
public void run() {
latch.countDown();
}
};
executor1.execute(worker);
}
latch.await();
ExecutorService executor2 = Executors.newFixedThreadPool(15);
for (int i = 0; i <= 15; i++) {
Runnable worker = new Runnable("Step 2 Insert");
executor2.execute(worker);
}
executor2.shutdown();