1. 程式人生 > >Spring @Async 註解的使用以及原理(一)

Spring @Async 註解的使用以及原理(一)

    Spring中用@Async註解標記的方法,稱為非同步方法,它會在呼叫方的當前執行緒之外的獨立的執行緒中執行,其實就相當於我們自己new Thread(()-> System.out.println("hello world !"))這樣在另一個執行緒中去執行相應的業務邏輯。本篇先只講@Async的使用,後面會分析它實現原理。

     @Async註解使用條件:

  1. @Async註解一般用在類的方法上,如果用在類上,那麼這個類所有的方法都是非同步執行的;
  2. 所使用的@Async註解方法的類物件應該是Spring容器管理的bean物件;
  3. 呼叫非同步方法類上需要配置上註解@EnableAsync

     我們在Spring Boot專案中做一下測試,測試程式碼如下:

非同步方法定義以及實現如下:

package com.example.service;

import org.springframework.scheduling.annotation.Async;

@Async
public interface TestService {
    void test();
}
package com.example.service.impl;

import com.example.service.TestService;
import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl implements TestService {
    @Override
    public void test() {
        System.out.println("ThreadName:" + Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("測試Spring 非同步呼叫!");
    }
}

 呼叫非同步方法的controller類程式碼如下:

package com.example.demo;

import com.example.model.PramInfo;
import com.example.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping(value = "/test")
@EnableAsync
public class TestContoller {

    @Autowired
    private TestService testService;

    @GetMapping(value = "/testAsync")
    public void print() {
        System.out.println("ThreadName:" + Thread.currentThread().getName());
        System.out.println("當前執行緒開始執行測試函式......");
        testService.test();
        for (int i = 1; i <= 100; i++) {
            System.out.print(i + " ");
            if (i % 10 == 0) {
                System.out.println();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("當前執行緒測試函式執行完畢......");
    }
}
ThreadName:http-nio-8080-exec-5
當前執行緒開始執行測試函式......
1 2 3 4 5 6 7 8 9 10 
ThreadName:SimpleAsyncTaskExecutor-2
測試Spring 非同步呼叫!
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 
41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 
61 62 63 64 65 66 67 68 69 70 
71 72 73 74 75 76 77 78 79 80 
81 82 83 84 85 86 87 88 89 90 
91 92 93 94 95 96 97 98 99 100 
當前執行緒測試函式執行完畢......

可以看出是有兩個執行緒在執行。如果我們去除TestController上的@EnableAsync或者new 一個TestService物件(該物件沒有載入進Spring的容器中),那麼TestController中的print()方法都會同步執行,後臺列印日誌也可以看到只有一個執行緒在執行:

ThreadName:http-nio-8080-exec-5
當前執行緒開始執行測試函式......
ThreadName:http-nio-8080-exec-5
測試Spring 非同步呼叫!
1 2 3 4 5 6 7 8 9 10 
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 
41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 
61 62 63 64 65 66 67 68 69 70 
71 72 73 74 75 76 77 78 79 80 
81 82 83 84 85 86 87 88 89 90 
91 92 93 94 95 96 97 98 99 100 
當前執行緒測試函式執行完畢......

後面會總結分析@Async註解的實現原理以及配置我們自己定義的執行器,還有就是分析非同步情況下的異常處理和事務處理等。