@Async prevent a thread to continue until other thread have finished

前端 未结 2 1219
我在风中等你
我在风中等你 2021-02-01 09:47

I have an application where for a certain number of times something needs to be calculated. This calculation function has the annotation @Async (from the Spring Framework), that

相关标签:
2条回答
  • 2021-02-01 10:25

    If you need to wait for the executions to finish, then you can return a Future as a return value, e.g.

    @Async
    public Future<Void> executeBla() {
        System.out.println("Bla!");
        return new AsyncResult<Void>(null);
    }
    

    This is slightly artificial, since there's no actual value being returned, but it will still allow the calling code to wait for all executions to finish:

    public void executeBlaALotOfTimes() {
        long before = System.currentTimeMillis();
    
        Collection<Future<Void>> futures = new ArrayList<Future<Void>>();
    
        for (int i = 0; i<40000; i++) {
            futures.add(executeBla());
        }
    
        for (Future<Void> future : futures) {
            future.get();
        }
    
        long after = System.currentTimeMillis(); 
    
        System.out.println("Time it took for a lot of bla to execute: " + (after - before) / 1000.0 + " seconds.");
    }
    

    Here, the first loop fires off the async tasks and stores the futures in a list. The seconds loop then iterates over the futures, waiting for each one to finish.

    0 讨论(0)
  • 2021-02-01 10:34

    An alternative is to return a ListenableFuture and to use a CountDownLatch.

    @Async
    public ListenableFuture<Void> executeBla() {
        try {
            System.out.println("Bla!");
            return AsyncResult.forValue(null);
        } catch (Throwable t) {
            return AsyncResult.forExecutionException(t);
        }
    }
    

    This scenario allows you to avoid explicitly calling future.get() for each future. You accomplish this by adding success and failure callbacks which in turn decrement the CountDownLatch, which was created exactly for this purpose.

    public void executeBlaALotOfTimes() {
        long before = System.currentTimeMillis();
    
        int numExecutions = 40000;
        CountDownLatch countDownLatch = new CountDownLatch(numExecutions);
    
        for (int i = 0; i<numExecutions; i++) {
            ListenableFuture<Void> future = executeBla();
            future.addCallback(
                aVoid -> countDownLatch.countDown(), 
                throwable -> countDownLatch.countDown()
            );
        }
    
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            // Handle exception
        } finally {
            long after = System.currentTimeMillis();
            System.out.println("Time it took for a lot of bla to execute: " + (after - before) / 1000.0 + " seconds.");
        }
    

    }

    0 讨论(0)
提交回复
热议问题