简体   繁体   English

执行器服务的异步过程

[英]Asynchronous process on Executor Service

I am using executor service for multi threading. 我正在使用执行程序服务进行多线程处理。 Spanned across 15 threads, current process does completes 15 threads before moving on to next executor services which is again spanned across 15 threads. 当前进程跨15个线程,当前进程确实完成了15个线程,然后再继续执行跨15个线程的下一个执行程序服务。 I am looking for code help where if any of current threads in step 1 executor services completes processing, i need to move on to next executor services which can start using the threads instead of waiting on completion of 15 threads in step 1 to complete. 我正在寻找代码帮助,如果第1步执行程序服务中的当前线程中的任何一个完成了处理,我需要继续使用下一个可以开始使用线程的执行程序服务,而不是等待第1步中完成15个线程来完成。

I want to utilize the threads completed and move on to step 2 even if other threads are getting executed in step1 and as soon as each thread in step 1 gets completed, step 2 can grab and continue processing. 即使要在步骤1中执行其他线程,我也要利用已完成的线程并继续执行步骤2,并且一旦步骤1中的每个线程完成,步骤2就可以抓取并继续进行处理。 Suggestions pls 建议

// 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();

You can use ExecutorCompletionService . 您可以使用ExecutorCompletionService I slightly modified example from JavaDoc 我从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 class is just for example and I assume it implements Callable or Runnable so it could be submitted into the second executor. Result类仅作为示例,我假设它实现CallableRunnable因此可以将其提交给第二个执行器。

You can also init instance of ExecutorService as new ThreadPoolExecutor(0, 15, 10, TimeUnit.SECONDS, new LinkedBlockingQueue()) to terminate threads which are not needed right now, but you want to reuse this executor later. 您还可以将ExecutorService实例初始化为new ThreadPoolExecutor(0, 15, 10, TimeUnit.SECONDS, new LinkedBlockingQueue())来终止当前不需要的线程,但是您以后想重用此执行器。

Or you can simply use one executor. 或者,您可以只使用一个执行程序。 After receiving a completed task from ExecutorCompletionService resubmit it (or its result) into the same executor (Thanks @Fildor). ExecutorCompletionService接收到已完成的任务后,将其(或其结果)重新提交给同一执行器(感谢@Fildor)。 But in this case you need to determine when task is completed first time. 但是在这种情况下,您需要确定任务首次完成的时间。

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()`
}

Why can't you just do all the steps in the same Runnable? 您为什么不能只在同一Runnable中执行所有步骤? eg 例如

ExecutorService executor = Executors.newFixedThreadPool(15);
for (int i=0;i<=15;i++) { 
    Runnable worker = new Runnable() {
        public void run() {
            doStep1();
            doStep2();
            doStep3();
            ...
        }
    }; 
    executor.execute(worker);
}
executor.shutdown();

@SpiderPig's answer is one good solution IMHO, yet I would like to give an alternative in case you want to decouple steps: @SpiderPig的答案是恕我直言的一个很好的解决方案,但是如果您想分离步骤,我想给出一个替代方案:

Use one single Executor, in your case the requirement seems to be a FixedThreadPool with 15 Threads. 使用一个执行器,您的需求似乎是带有15个线程的FixedThreadPool。

Next would be to define Step-Runnables like so: 接下来将是定义Step-Runnable,如下所示:

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.
    }
} 

You can see that I used a State object, which holds all data you need to perform the steps and collect the result. 您可以看到我使用了State对象,该对象保存执行步骤和收集结果所需的所有数据。 Of course you'd need to define StepX as Step1, Step2, ... 当然,您需要将StepX定义为Step1,Step2,...

In the outer class, you'd only have to submit N Step1-Runnables and it will only use your 15 Threads and go through the steps. 在外部类中,您只需提交N个Step1-Runnables,它将仅使用您的15个线程并完成各个步骤。

I left out a means to signal when all steps are done, because there are plenty of possibilities to do this and I am sure you can pick one by yourself. 我遗漏了一种在所有步骤完成时发出信号的方式,因为这样做的可能性很大,我相信您可以自己选择一个。

You can try use CountDownLatch class. 您可以尝试使用CountDownLatch类。

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM