Java set a callback from ExecutorService

前端 未结 4 827
一整个雨季
一整个雨季 2020-12-31 09:29

I have a fixedThreadPool that I am using to run a bunch of worker threads to achieve parallel execution of a task with many components.

When all threads have finishe

相关标签:
4条回答
  • 2020-12-31 09:42

    So, I was wondering if it's possible to attach a callback function to the event of a thread finishing using the ExecutorService.

    Not directly, no, but there are a couple of ways you could accomplish this. The easiest way that comes to mind is to wrap your Runnable in another Runnable that does the reaping of the results.

    So you'd do something like:

    threadPool.submit(new ResultPrinter(myRunnable));
    ...
    
    private static class ResultPrinter implements Runnable {
        private final MyRunnable myRunnable;
        public ResultPrinter(MyRunnable myRunnable) {
            this.myRunnable = myRunnable;
        }
        public void run() {
            myRunnable.run();
            Results results = myRunnable.getResults();
            // print results;
        }
    }
    
    0 讨论(0)
  • 2020-12-31 09:45

    You can add a callback for when a thread returns in Java 8+ using CompletableFuture as in the following, where t is the result of your long-running computation,

    CompletableFuture.supplyAsync(() -> {
        T t = new T();
        // do something
        return t;
    }).thenApply(t -> {
        // process t
    });
    

    If you want to use callbacks in just Java 7, you could do something like,

    int x = 10;
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(x);
    Future<T> result = fixedThreadPool.submit(() -> {
        // do calculation
        return T;
    });
    fixedThreadPool.submit(() -> {
        long minutesToWait = 5;
        T t = null;
        try {
            t = result.get(minutesToWait, TimeUnit.MINUTES);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            LOGGER.error(e);
        }
        if (t != null) {
            // process t
        }
    });
    
    0 讨论(0)
  • 2020-12-31 09:51

    ExecutorService#submit return FutureTask<T> which helps you to retrieve result and the ExecutorService#get method will block execution until the computation is not completed. Example -

    ExecutorService executor = Executors.newFixedThreadPool(10);
    Future<Long> future = executor.submit(new Callable<Long>(){
           @Override
           public Long call() throws Exception {
               long sum = 0;
               for (long i = 0; i <= 10000000l; i++) {
                   sum += i;
               }
               return sum;
           }
    });
    Long result = future.get();
    System.out.println(result);
    
    0 讨论(0)
  • 2020-12-31 09:54

    If using Google Guava is an option, you could utilize the ListenableFuture interface in the following manner:

    1. Convert an ExecutorService to a ListeningExecutorService via MoreExecutors.listeningDecorator(existingExecutorService)
    2. The submit(Callable<V>) method of ListeningExecutorService has been narrowed to return a ListenableFuture, which is a subinterface of Future.
    3. ListenableFuture has an addListener() method so you can register a callback to be run when the future is completed.
    0 讨论(0)
提交回复
热议问题