如何在没有特定订单的情况下管理多个可调用线程结果?

时间:2017-06-15 23:27:48

标签: java multithreading performance threadpool callable

基本上是这样的:

ExecutorService service = Executors.newFixedThreadPool(2);

Future<Boolean> futureFoo = service.submit(myFooTask);
Future<Boolean> futureBar = service.submit(myBarTask);

int resultFoo;
boolean resultBar;
resultFoo = futureFoo.get();
resultBar = futureBar.get();

我想做一个事件来独立管理我得到的第一个结果,而不是等待futureFoo先完成。

2 个答案:

答案 0 :(得分:2)

您可以使用CompletionService。将callable的结果放入队列中,您可以在完成任务后立即获取结果。

在这种情况下,如果Bar先前完成,您不需要等待Foo的结果。

例如:

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CompletionServiceExample {


    private static Logger LOGGER = Logger.getLogger("CompletionServiceExample");

    public static void main(String[] args) throws InterruptedException {

        CompletionServiceExample completionServiceExample = new CompletionServiceExample();
        completionServiceExample.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        final ExecutorService executorService = Executors.newFixedThreadPool(2);
        final CompletionService<Boolean> completionService = new ExecutorCompletionService<>(executorService);


        completionService.submit(new Foo());
        completionService.submit(new Bar());

        int total_tasks = 2;

        for(int i = 0; i < total_tasks; ++i) {

            try {
                final Future<Boolean> value = completionService.take();
                System.out.println("received value: " + value.get());
            } catch (ExecutionException e) {
                LOGGER.log(Level.WARNING, "Error while processing task. ", e);
            } catch (InterruptedException e) {
                LOGGER.log(Level.WARNING, "interrupted while waiting for result", e);
            }
        }


        executorService.shutdown();
        executorService.awaitTermination(5, TimeUnit.SECONDS);

    }
}

class Foo implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        Thread.sleep(5000);
        return true;
    }
}

class Bar implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        Thread.sleep(1000);
        return false;
    }
}

答案 1 :(得分:1)

如果要返回不同的类型,可以使用基类进行向下转换。例如:

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CompletionServiceExample {


    private static Logger LOGGER = Logger.getLogger("CompletionServiceExample");

    public static void main(String[] args) throws InterruptedException {

        CompletionServiceExample completionServiceExample = new CompletionServiceExample();
        completionServiceExample.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        final ExecutorService executorService = Executors.newFixedThreadPool(2);
        final CompletionService<Base> completionService = new ExecutorCompletionService<>(executorService);


        completionService.submit(new FooBase());
        completionService.submit(new BarBase());

        int total_tasks = 2;

        for (int i = 0; i < total_tasks; ++i) {

            try {
                final Future<Base> value = completionService.take();
                Base base = value.get();
                if (base instanceof FooBase) {
                    int myInteger = ((FooBase) base).getValue();
                    System.out.println("received value: " + myInteger);
                }
                if (base instanceof BarBase) {
                    boolean myBoolean = ((BarBase) base).isValue();
                    System.out.println("received value: " + myBoolean);
                }

            } catch (ExecutionException e) {
                LOGGER.log(Level.WARNING, "Error while processing task. ", e);
            } catch (InterruptedException e) {
                LOGGER.log(Level.WARNING, "interrupted while waiting for result", e);
            }
        }


        executorService.shutdown();
        executorService.awaitTermination(5, TimeUnit.SECONDS);

    }
}

class Base {
}

class FooBase extends Base implements Callable<Base> {

    private int value;

    @Override
    public Base call() throws Exception {
        Thread.sleep(5000);
        value = 10;
        return this;
    }

    public int getValue() {
        return value;
    }
}

class BarBase extends Base implements Callable<Base> {

    private boolean value;

    @Override
    public Base call() throws Exception {
        Thread.sleep(1000);
        value = false;
        return this;
    }

    public boolean isValue() {
        return value;
    }
}