Executor Service上的异步流程

时间:2016-01-25 14:46:17

标签: java multithreading asynchronous executorservice

我正在使用执行程序服务进行多线程处理。跨越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();

4 个答案:

答案 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类仅作为示例,我假设它实现了CallableRunnable,因此可以将其提交到第二个执行程序中。

您还可以将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();