zoukankan      html  css  js  c++  java
  • Async分析

    如何在Spring中启用@Async

           基于Java配置的启用方式:

    [html] view plain copy
     
    1. @Configuration  
    2. @EnableAsync  
    3. public class SpringAsyncConfig { ... }  

         基于XML配置文件的启用方式,配置如下:

    [html] view plain copy
     
    1. <task:executor id="myexecutor" pool-size="5"  />  
    2. <task:annotation-driven executor="myexecutor"/>  

       以上就是两种定义的方式。

    4. 基于@Async无返回值调用

        示例如下:

    [html] view plain copy
     
    1. @Async  //标注使用  
    2. public void asyncMethodWithVoidReturnType() {  
    3.     System.out.println("Execute method asynchronously. "  
    4.       + Thread.currentThread().getName());  
    5. }  

      使用的方式非常简单,一个标注即可解决所有的问题。

    5. 基于@Async返回值的调用

       示例如下:

    [html] view plain copy
     
    1. @Async  
    2. public Future<String> asyncMethodWithReturnType() {  
    3.     System.out.println("Execute method asynchronously - "  
    4.       + Thread.currentThread().getName());  
    5.     try {  
    6.         Thread.sleep(5000);  
    7.         return new AsyncResult<String>("hello world !!!!");  
    8.     } catch (InterruptedException e) {  
    9.         //  
    10.     }  
    11.    
    12.     return null;  
    13. }  

       以上示例可以发现,返回的数据类型为Future类型,其为一个接口。具体的结果类型为AsyncResult,这个是需要注意的地方。

       调用返回结果的异步方法示例:

    [html] view plain copy
     
    1. public void testAsyncAnnotationForMethodsWithReturnType()  
    2.    throws InterruptedException, ExecutionException {  
    3.     System.out.println("Invoking an asynchronous method. "  
    4.       + Thread.currentThread().getName());  
    5.     Future<Stringfuture = asyncAnnotationExample.asyncMethodWithReturnType();  
    6.    
    7.     while (true) {  ///这里使用了循环判断,等待获取结果信息  
    8.         if (future.isDone()) {  //判断是否执行完毕  
    9.             System.out.println("Result from asynchronous process - " + future.get());  
    10.             break;  
    11.         }  
    12.         System.out.println("Continue doing something else. ");  
    13.         Thread.sleep(1000);  
    14.     }  
    15. }  

      分析: 这些获取异步方法的结果信息,是通过不停的检查Future的状态来获取当前的异步方法是否执行完毕来实现的。

    6. 基于@Async调用中的异常处理机制

        在异步方法中,如果出现异常,对于调用者caller而言,是无法感知的。如果确实需要进行异常处理,则按照如下方法来进行处理:

        1.  自定义实现AsyncTaskExecutor的任务执行器

             在这里定义处理具体异常的逻辑和方式。

        2.  配置由自定义的TaskExecutor替代内置的任务执行器

        示例步骤1,自定义的TaskExecutor

    [html] view plain copy
     
    1. public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor {  
    2.     private AsyncTaskExecutor executor;  
    3.     public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) {  
    4.         this.executor = executor;  
    5.      }  
    6.       ////用独立的线程来包装,@Async其本质就是如此  
    7.     public void execute(Runnable task) {       
    8.       executor.execute(createWrappedRunnable(task));  
    9.     }  
    10.     public void execute(Runnable task, long startTimeout) {  
    11.         /用独立的线程来包装,@Async其本质就是如此  
    12.        executor.execute(createWrappedRunnable(task), startTimeout);           
    13.     }   
    14.     public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task));  
    15.        //用独立的线程来包装,@Async其本质就是如此。  
    16.     }   
    17.     public Future submit(final Callable task) {  
    18.       //用独立的线程来包装,@Async其本质就是如此。  
    19.        return executor.submit(createCallable(task));   
    20.     }   
    21.       
    22.     private Callable createCallable(final Callable task) {   
    23.         return new Callable() {   
    24.             public T call() throws Exception {   
    25.                  try {   
    26.                      return task.call();   
    27.                  } catch (Exception ex) {   
    28.                      handle(ex);   
    29.                      throw ex;   
    30.                    }   
    31.                  }   
    32.         };   
    33.     }  
    34.   
    35.     private Runnable createWrappedRunnable(final Runnable task) {   
    36.          return new Runnable() {   
    37.              public void run() {   
    38.                  try {  
    39.                      task.run();   
    40.                   } catch (Exception ex) {   
    41.                      handle(ex);   
    42.                    }   
    43.             }  
    44.         };   
    45.     }   
    46.     private void handle(Exception ex) {  
    47.       //具体的异常逻辑处理的地方  
    48.       System.err.println("Error during @Async execution: " + ex);  
    49.     }  
    50. }  


     分析: 可以发现其是实现了AsyncTaskExecutor, 用独立的线程来执行具体的每个方法操作。在createCallable和createWrapperRunnable中,定义了异常的处理方式和机制。

    
    

    handle()就是未来我们需要关注的异常处理的地方。

          配置文件中的内容:

    [html] view plain copy
     
    1. <task:annotation-driven executor="exceptionHandlingTaskExecutor" scheduler="defaultTaskScheduler" />  
    2. <bean id="exceptionHandlingTaskExecutor" class="nl.jborsje.blog.examples.ExceptionHandlingAsyncTaskExecutor">  
    3.     <constructor-arg ref="defaultTaskExecutor" />  
    4. </bean>  
    5. <task:executor id="defaultTaskExecutor" pool-size="5" />  
    6. <task:scheduler id="defaultTaskScheduler" pool-size="1" />  

      分析: 这里的配置使用自定义的taskExecutor来替代缺省的TaskExecutor。

    7. @Async调用中的事务处理机制

        在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。

         那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.

        例如:  方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。

              方法B,使用了@Async来标注,  B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。

    8. 总结

         通过以上的描述,应该对@Async使用的方法和注意事项了。

  • 相关阅读:
    Educational Codeforces Round 67 D. Subarray Sorting
    2019 Multi-University Training Contest 5
    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
    Educational Codeforces Round 69 D. Yet Another Subarray Problem
    2019牛客暑期多校训练第六场
    Educational Codeforces Round 68 E. Count The Rectangles
    2019牛客多校第五场题解
    2019 Multi-University Training Contest 3
    2019 Multi-University Training Contest 2
    [模板] 三维偏序
  • 原文地址:https://www.cnblogs.com/liupeixuan/p/8647592.html
Copyright © 2011-2022 走看看