Notes @Async solve the problem of asynchronous call

Preamble: Spring in @Async

According to Spring documentation, the default uses a single-threaded mode. So in Java applications, most cases are achieved through interactive processing synchronized manner.

Then when the execution of multiple tasks is bound to affect each other. For example, if A task execution time is longer, then B must wait until the task is finished A task will start execution. Another example is when dealing with third-party systems to interact, likely to cause slow response to the situation, before most of them are using multiple threads to complete such tasks, in fact, after spring3.x, has built the perfect solution to this @Async problem.

1. What is an asynchronous call?

Before I explain, let’s look at two definitions:

Synchronous call: execution order, wait on a task is finished

The entire process is performed sequentially, when the various processes are executed, and returns the result.

Asynchronous call: receiving the instruction is executed without waiting

It is just to send a command to call, the caller without waiting for the method to be called completely finished; but continue with the following procedure.

For example, in a call, call A, B, C during three sequential method:
    As they are synchronous call, then they need to be finished after the order, the process is finished side count; if B is an asynchronous invocation method, after running A, B calls, without waiting for the completion of B, and the implementation start calling C, until after the C is finished, it means that the process is finished.

如图所示:

2. The conventional asynchronous call handling

After time in Java, usually in the treatment of similar scenes are created based on a separate thread asynchronous call to complete the corresponding logic through the execution flow between the main thread and the different threads, so start a separate thread, the main thread to continue without creating stagnant situation of waiting. Or use TaskExecutor perform asynchronous thread, see http://www.cnblogs.com/wihainan/p/6098970.html

3. How to enable @Async in Spring?

3.0, @ Async introduction

In Spring, the method @Async based tagging, called asynchronous methods; these methods when executed, will be executed in a separate thread, the caller without waiting for its completion, we can continue with other operations.

3.1, enable @Async comment

3.1.1, Java-based way to enable configuration:

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

3.1.2, based SpringBoot configuration mode is enabled:

@SpringBootApplication
@EnableAsync
public class SpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication.class, args);
    }
}

3.2, using @Async annotation, declare an asynchronous method call

3.2.0 In the method using no return value:

Affirming asynchronous method to invoke methods on

    @Async //标注使用
    public void downloadFile() throws Exception { ... } 

3.2.1, the return value using methods:

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

Can be found in the above example, the data type returned by Future type, which is an interface. Specific results types AsyncResult, this is the place to note.

Examples of asynchronous method call returns a result:

public void testAsyncAnnotationForMethodsWithReturnType()  
   throws InterruptedException, ExecutionException {  
    System.out.println("Invoking an asynchronous method. "   + Thread.currentThread().getName());  
    Future 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);  
    }  
}

These asynchronous methods to obtain information about the result, is to get the current asynchronous method if finished achieved by constantly checking Future state.

4. @Async call exception handling mechanism based on

In the asynchronous method, if an exception occurs, the caller caller, it can not be perceived. If you do need for exception handling, the process is performed as follows:

    Custom implementation AsyncTaskExecutor task executor
            It is defined herein as exception handling logic and specific manner.

    Configuring TaskExecutor replaced by a custom built task executor
            Example Step 1, custom 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);  
    }  
}

Analysis: it may be found to achieve AsyncTaskExecutor, performed with a separate thread for each specific operation method. In createCallable and createWrapperRunnable, the definition of exception handling methods and mechanisms.

handle () is where exception handling in the future we need to focus on.
    xml configuration file contents:

  
  
      
  
  

It can also be used in the form of annotations to configure it to register the bean.

Transaction processing 5. @Async invocation

In the method @Async labeling, as well as the @Transactional be labeled; when they call database operation, the control transaction management will not produce, the reason lies in its operation is based on asynchronous processing.

How to add that the transaction manager to do these operations?

The method requires transaction management operations can be placed inside the asynchronous method, add @Transactional on internal method is called

Example:

Method A, using the @ Async / @ Transactional be marked, but not the purpose of generating transaction control.

Method B, used to mark the @Async, B calls the object C, D, C / D are respectively denoted by the @Transactional made, transaction control can be realized.

6. Reference article:

[1]、https://www.cnblogs.com/wihainan/p/6516858.html
[2]、http://www.cnblogs.com/wihainan/p/6098970.html

Leave a comment