2

我正在尝试在我的 Service 类中实现并发方法调用。

我的服务类中有一些方法被注释为@Async,我正在尝试同时调用所有这些方法。但是这些方法是按顺序执行的。

这是我的服务类(虚拟):

@Service public class TestService {

public SomeDataType getSOmeDataType() {
        try {
            List<DataType> a = retrieveDataA().get();
            List<DataType> b = retrieveDataB().get();
            List<DataType> c = retrieveDataC().get();
            List<DataType> d = retrieveDataD().get();
            List<DataType> e = retrieveDataE().get();           
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        catch (ExecutionException e) {
            e.printStackTrace();
        }
        return referralDetailsReferenceData;
    }

@Async 
    private Future<List<DataType>> retrieveDataA() {
        //method logic
    }

@Async 
    private Future<List<DataType>> retrieveDataB() {
        //method logic
    }

@Async 
    private Future<List<DataType>> retrieveDataC() {
        //method logic
    }

@Async 
    private Future<List<DataType>> retrieveDataD() {
        //method logic
    }

@Async 
    private Future<List<DataType>> retrieveDataE() {
        //method logic
    }

这是我的弹簧配置:

<bean id="executorService" class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
    <constructor-arg value="10" />
</bean>

<task:executor id="threadPoolTaskExecutor" pool-size="10" />

<task:annotation-driven executor="executorService" />

当“getSomeDataType”被执行时,方法被顺序调用。

我是 @Async 和 Spring 中的并发执行的新手,所以我确定我在做一些愚蠢的事情。但我无法弄清楚。

任何建议都非常感谢。

4

1 回答 1

23

问题是您在内部调用这些方法,因此它们不会被代理。为了@Async工作,您需要从应用程序上下文中检索对象并调用检索到的副本上的方法。在内部调用它是行不通的。

如果您尝试调用内部@Transactional方法,也会发生同样的事情。有关详细信息,请参阅Spring文档末尾的Note:部分。@Transactional

此外,您立即调用返回值的方式不正确.get()Future如果您希望它们并行发生,您应该提交所有任务,然后通过.get().

处理代理问题的常用方法是创建一个单独的服务类,将TestService其注入其中并@Async直接调用服务方法:

@Service public class TestServiceHelper {
    @Autowired
    TestService testService;

    public SomeDataType getSOmeDataType() {
        try {
            // Invoke all of them async:
            Future<List<DataType>> a = testService.retrieveDataA();
            Future<List<DataType>> b = testService.retrieveDataA();
            Future<List<DataType>> c = testService.retrieveDataA();
            Future<List<DataType>> d = testService.retrieveDataA();
            Future<List<DataType>> e = testService.retrieveDataA();

            // Wait for each sequentially:
            List<DataType> aList = a.get();
            List<DataType> bList = b.get();
            List<DataType> cList = c.get();
            List<DataType> dList = d.get();
            List<DataType> eList = e.get();

            // do work with lists here ...
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        catch (ExecutionException e) {
            e.printStackTrace();
        }
        return referralDetailsReferenceData;
    }
}

上述单独服务 bean 的替代方案(相当 hackish/不推荐!)是将对象注入自身并使用注入的副本来调用@Async方法。

于 2013-07-18T23:22:01.570 回答