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 ドキュメントの説明の最後にある注:セクションを参照してください。@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 (非常にハック的/非推奨!) の代わりに、オブジェクトをそれ自体に注入し、注入されたコピーを使用して@Asyncメソッドを呼び出すこともできます。

于 2013-07-18T23:22:01.570 に答える