32

Spring 4 を使用していますが、奇妙な動作に気付きました...通常のインスタンス メソッドから async メソッドを複数回呼び出すと、それらはすべて異なるスレッドで呼び出され、ランダムな時間に終了します。しかし、別の非同期メソッドから非同期メソッドを複数回呼び出すと、順番に終了します。私はこのようなものを持っています:

@Async
public void nonAsyncMethod() {
  for (int i = 0; i < 30; i++) {
     asyncMethod();
  }
}

@Async
public void asyncMethod() {
   ... something here
}

デフォルトの非同期エグゼキュータを使用しています。別のものを使用する必要がありますか?ただし、このエグゼキュータはスレッドを再利用せず、毎回別のスレッドを開始するため、問題ないはずです...単なる偶然でしょうか? しかし、私は10回以上試しましたが、最初の方法で非非同期に戻すと、ランダムに終了します

4

1 に答える 1

73

あなたが説明しているのは、Spring AOP の典型的な落とし穴です。

つまり、Spring が非同期動作を提供できるようにするには、実行時にクラスのプロキシを作成する必要があります。次に、プロキシは、コードを呼び出す前および/または後に必要なことをすべて実行します。しかし、あなたの場合、プロキシメカニズムは2番目の方法に適用されていません.

クラスの Bean が Spring を介して他のコンポーネントに注入されると、Spring は代わりにプロキシを実際に注入します。そのため、プロキシの関連するメソッドが呼び出されます。ただし、クラス内からメソッドを呼び出す場合、Spring AOP の制限により、プロキシが機能することはなく、代わりに通常のメソッドが呼び出され、追加機能はありません。

そのため、asyncMethodは常に、それを呼び出した同じクラスの他のメソッドと同じスレッドで実行されます。

この優れたブログ投稿と、Spring ドキュメントのこの部分を確認してください。

コードをリファクタリングする必要のない問題を回避する方法がいくつかあります (これを確認してください)。ただし、非同期を両方のメソッドで動作させたい場合は、2 番目のメソッドを別のクラスにリファクタリングするのが最も簡単な方法です。 .

于 2014-07-23T05:20:54.160 に答える