@Async prevent线程继续下去,直到其他线程完成 [英] @Async prevent a thread to continue until other thread have finished

查看:288
本文介绍了@Async prevent线程继续下去,直到其他线程完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有其中用于一个特定的次数的东西需要计算的应用程序。该计算功能有注解@Async(从Spring框架),这使得它能够在4个线程运行这些计算。问题是,我需要这些计算的40000左右,我想知道的开始和所有的计算结束之间的时间,让我看看这是什么时候之前和之后的for循环调用的计算功能。但是现在所有的计算都放在一个队列中,以便for循环立即结束和时间是一样的东西1秒,而这需要几个小时的计算来完成。我已经尝试了最大队列大小设置为100(也很好地减少内存使用),不过这也是没有办法,因为我将在所花费的总时间错过了最后100计算。有没有一种方法来暂停执行code中的for循环,直到所有线程都完成后,刚做他们的工作,但仍然能够使用@Async注解?

这是一些code,说明了同样的问题:

执行类:

 公共类Foo {
    公共无效executeBlaALotOfTimes(){
        没过多久= System.currentTimeMillis的();        的for(int i = 0; I< 40000;我++){
            executeBla();
        }        长= System.currentTimeMillis的()之后;        的System.out.println(时间花了很多血乳酸的执行:+(后 - 前)/ 1000.0 +秒);
    }
}

和执行计算类:

  @Service
公共类酒吧{
    @Async
    公共无效executeBla(){
        的System.out.println(布拉!);
    }
}

这将导致下面的输出(假设Foo中的code执行无限快):


时间花了很多血乳酸的执行:0.0秒。
布拉!
布拉!
布拉!
布拉!



等等


解决方案

如果您需要等待处决完成,那么你可以返回一个未来作为返回值,如:

  @Async
公共未来<无效> executeBla(){
    的System.out.println(布拉!);
    返回新AsyncResult<无效>(NULL);
}

这是稍微人为的,因为没有返回没有实际价值,但它仍然会允许调用code等待所有执行完成:

 公共无效executeBlaALotOfTimes(){
    没过多久= System.currentTimeMillis的();    收集和LT;未来<无效>>期货=新的ArrayList<&未来LT;无效>>();    的for(int i = 0; I< 40000;我++){
        futures.add(executeBla());
    }    对于(未来<无效>的未来:期货){
        的Future.get();
    }    长= System.currentTimeMillis的()之后;    的System.out.println(时间花了很多血乳酸的执行:+(后 - 前)/ 1000.0 +秒);
}

下面,第一环路打完列表中的异步任务并存储期货。秒循环在期货迭代,等待着每一个来完成。

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 makes it possible to run these calculations on 4 threads. The problem is that I need about 40000 of these calculations and I want to know the time between the start and end of all the calculations, so I see what time it is before and after the for-loop that calls the calculation functions. But now all the calculations are put in a queue, so the for loop finishes immediately and the time is something like 1 second, while it takes a couple of hours for the calculations to complete. I've tried setting a max queue size to about 100 (also good to reduce memory usage) but this is also no solution since I'll miss the last 100 calculations in the total time it takes. Is there a way to pause the executing code just after the for loop until all threads have finished doing their work, but still being able to use the @Async annotation?

This is some code that illustrates the same problem:

Executing class:

public class Foo {
    public void executeBlaALotOfTimes() {
        long before = System.currentTimeMillis();

        for (int i = 0; i<40000; i++) {
            executeBla();
        }

        long after = System.currentTimeMillis(); 

        System.out.println("Time it took for a lot of bla to execute: " + (after - before) / 1000.0 + " seconds.");
    }
}

And the class that performs the calculations:

@Service
public class Bar {
    @Async
    public void executeBla() {
        System.out.println("Bla!");
    }
}

This would result in the following output (assuming the code in Foo executes infinitely fast):

Time it took for a lot of bla to execute: 0.0 seconds.
Bla!
Bla!
Bla!
Bla!
.
.
.
etc

解决方案

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.

这篇关于@Async prevent线程继续下去,直到其他线程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆