ホームページ >Java >&#&チュートリアル >Springでの@Asyncの使い方の詳しい説明と簡単なサンプル紹介

Springでの@Asyncの使い方の詳しい説明と簡単なサンプル紹介

黄舟
黄舟オリジナル
2017-03-07 10:12:131664ブラウズ

この記事では Spring での @Async の使い方の詳しい説明と簡単な例を中心に紹介しますので、必要な方は参考にしてください

Spring での @Async の使い方

はじめに: Java アプリケーションでは、ほとんどの場合、対話処理が行われます。ただし、サードパーティのシステムと対話する場合、そのようなタスクを完了するために、そのほとんどがマルチスレッドを使用していました。この問題を完全に解決するために Async が組み込まれています。この記事では @Async の使用法を完全に紹介します。

1. 非同期呼び出しとは何ですか?

非同期呼び出しを説明する前に、まず同期呼び出しの定義を見てみましょう。同期とは、処理プロセス全体が順番に実行され、各プロセスが完了すると結果が返されることを意味します。 非同期呼び出しは呼び出し命令を送信するだけであり、呼び出し元は呼び出されたメソッドが完全に実行されるまで待つ必要がなく、代わりに次のプロセスを実行し続けます。

たとえば、ある呼び出しでは、3 つのプロセス メソッド A、B、および C を順番に呼び出す必要があります。これらがすべて同期呼び出しである場合は、プロセスの実行が完了する前にそれらを順番に実行する必要があります。非同期呼び出しメソッドは、Aを実行した後、Bを呼び出します。Bの完了を待たずに実行を開始し、Cを呼び出します。Cが完了すると、処理が完了したことになります。

2. 従来の非同期呼び出し処理方法

Java では、同様のシナリオを処理する場合、通常、メインスレッドと別のスレッドを通じて、対応する非同期呼び出しロジックを完了するための独立したスレッドを作成することに基づいています。独立したスレッドである場合、メインスレッドは停止したり待機したりすることなく実行を続けます。

3. @Async の概要

Spring では、@Async アノテーションに基づくメソッドは非同期メソッドと呼ばれ、これらのメソッドは実行時に独立したスレッドで実行され、呼び出し元は完了後に待つ必要がありません。をクリックすると、他の操作を続行できます。

Spring で @Async を有効にする方法

Java 設定に基づくアクティベーション:

@Configuration 
@EnableAsync 
public class SpringAsyncConfig { ... }

XML 設定ファイルに基づくアクティベーション、設定は次のとおりです:

<task:executor id="myexecutor" pool-size="5" /> 
<task:annotation-driven executor="myexecutor"/>

上記 2 つの定義があります方法。

4. @Async に基づく戻り値なしの呼び出し

例は次のとおりです:

@Async //标注使用 
public void asyncMethodWithVoidReturnType() { 
  System.out.println("Execute method asynchronously. " 
   + Thread.currentThread().getName()); 
}

使用方法は非常に簡単で、1 つのアノテーションですべての問題を解決できます。

5. @Async の戻り値に基づいて呼び出します

例は次のとおりです:

@Async 
public Future<String> asyncMethodWithReturnType() { 
  System.out.println("Execute method asynchronously - " 
   + Thread.currentThread().getName()); 
  try { 
    Thread.sleep(5000); 
    return new AsyncResult<String>("hello world !!!!"); 
  } catch (InterruptedException e) { 
    // 
  } 
  
  return null; 
}

上記の例から、返されるデータ型はインターフェイスである Future 型であることがわかります。 。特定の結果タイプは AsyncResult であるため、注意が必要です。

結果を返す非同期メソッドの呼び出し例:

public void testAsyncAnnotationForMethodsWithReturnType() 
  throws InterruptedException, ExecutionException { 
  System.out.println("Invoking an asynchronous method. " 
   + Thread.currentThread().getName()); 
  Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType(); 
  
  while (true) { ///这里使用了循环判断,等待获取结果信息 
    if (future.isDone()) { //判断是否执行完毕 
      System.out.println("Result from asynchronous process - " + future.get()); 
      break; 
    } 
    System.out.println("Continue doing something else. "); 
    Thread.sleep(1000); 
  } 
}

分析: 非同期メソッドの結果情報の取得は、Future のステータスを常にチェックして、現在の非同期メソッドが実行されたかどうかを取得することによって実現されます。実行されました。

6. @Async 呼び出しの例外処理メカニズムに基づく

非同期メソッドでは、例外が発生しても呼び出し元はそれを認識しません。例外処理が実際に必要な場合は、次のように処理します。

1. AsyncTaskExecutor を実装するタスク エグゼキュータをカスタマイズします

ここで、特定の例外を処理するロジックとメソッドを定義します。

2. 組み込みのタスク エグゼキューターを置き換えるためにカスタム TaskExecutor を構成します

ステップ 1 の例、カスタム TaskExecutor

public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor { 
  private AsyncTaskExecutor executor; 
  public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) { 
    this.executor = executor; 
   } 
   ////用独立的线程来包装,@Async其本质就是如此 
  public void execute(Runnable task) {    
   executor.execute(createWrappedRunnable(task)); 
  } 
  public void execute(Runnable task, long startTimeout) { 
    /用独立的线程来包装,@Async其本质就是如此 
    executor.execute(createWrappedRunnable(task), startTimeout);      
  }  
  public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task)); 
    //用独立的线程来包装,@Async其本质就是如此。 
  }  
  public Future submit(final Callable task) { 
   //用独立的线程来包装,@Async其本质就是如此。 
    return executor.submit(createCallable(task));  
  }  
   
  private Callable createCallable(final Callable task) {  
    return new Callable() {  
      public T call() throws Exception {  
         try {  
           return task.call();  
         } catch (Exception ex) {  
           handle(ex);  
           throw ex;  
          }  
         }  
    };  
  } 
 
  private Runnable createWrappedRunnable(final Runnable task) {  
     return new Runnable() {  
       public void run() {  
         try { 
           task.run();  
         } catch (Exception ex) {  
           handle(ex);  
          }  
      } 
    };  
  }  
  private void handle(Exception ex) { 
   //具体的异常逻辑处理的地方 
   System.err.println("Error during @Async execution: " + ex); 
  } 
}

分析: 独立したスレッドを使用して特定のタスクを実行する AsyncTaskExecutor を実装していることがわかります。メソッドが動作します。 createCallableとcreateWrapperRunnableでは、例外処理のメソッドと機構が定義されています。

handle() は、今後例外処理に焦点を当てる必要がある場所です。

構成ファイルの内容:

<task:annotation-driven executor="exceptionHandlingTaskExecutor" scheduler="defaultTaskScheduler" /> 
<bean id="exceptionHandlingTaskExecutor" class="nl.jborsje.blog.examples.ExceptionHandlingAsyncTaskExecutor"> 
  <constructor-arg ref="defaultTaskExecutor" /> 
</bean> 
<task:executor id="defaultTaskExecutor" pool-size="5" /> 
<task:scheduler id="defaultTaskScheduler" pool-size="1" />

分析: ここの構成では、カスタム taskExecutor を使用してデフォルトの TaskExecutor を置き換えます。

7. @Async 呼び出しのトランザクション処理メカニズム

@Async でマークされたメソッドは、データベース操作を呼び出すときにも @Transactional でマークされ、トランザクション管理制御は生成されません。非同期処理に基づいています。

では、これらの操作にトランザクション管理を追加するにはどうすればよいでしょうか?トランザクション管理操作が必要なメソッドは非同期メソッド内に配置でき、内部で呼び出されるメソッドに @Transactional.

が追加されます。例: メソッド A は @Async/@Transactional でマークされていますが、トランザクションの目的を達成できません。コントロール。

メソッド B には @Async アノテーションが付けられ、C と D は B で呼び出されます。C/D にはそれぞれ @Transactional アノテーションが付けられ、トランザクション制御の目的を達成できます。

8. まとめ

上記の説明を通じて、@Async を使用する方法と注意事項を理解する必要があります。

上記は、Spring での @Async の使用方法の詳細な説明と簡単な例です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。