天天看點

Spring異步

1.1 xml配置

<task:annotation-driven executor="asyncExecutor" />

<task:executor id="asyncExecutor" pool-size="100-10000" queue-capacity="10"/>
           

1.2 java配置

@Configuration  
@EnableAsync  //開啟異步
public class SpringConfig {  
    private int corePoolSize = 10;  
    private int maxPoolSize = 200;  
    private int queueCapacity = 10;  

     private String ThreadNamePrefix = "MyLogExecutor-";  

    @Bean("asyncService1") 
    public Executor logExecutor() {  
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();  
        executor.setCorePoolSize(corePoolSize);  
        executor.setMaxPoolSize(maxPoolSize);  
        executor.setQueueCapacity(queueCapacity);  
        executor.setThreadNamePrefix(ThreadNamePrefix);  
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());  
        executor.initialize();  
        return executor;  
    }  
} 

@Component
@Async("asyncService1") //當調用改方法時,會異步調用和@Bean中參數對應
public class AsyncService {
	public void testAsync() {
	    System.out.println("begin..開始調用");
	    try {
	    	Thread.sleep(10000);
	    } catch (InterruptedException e) {
	    	System.out.println("睡眠");
    	}
    	System.out.println("end...結束調用");
    }
}
           

1.3 異步任務類

Service

@Component
public class AsyncTask {
	
	@Async
	public Future<String> task1() throws InterruptedException{
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(1000);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task1任務耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
		return new AsyncResult<String>("task1執行完畢");
	}
	
	@Async
	public Future<String> task2() throws InterruptedException{
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(2000);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task2任務耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
		return new AsyncResult<String>("task2執行完畢");
	}
	@Async
	public Future<String> task3() throws InterruptedException{
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(3000);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task3任務耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
		return new AsyncResult<String>("task3執行完畢");
	}
}

           

Controller

@RequestMapping("")
@RestController
public class AsyncTaskController {
	
	@Autowired
	private AsyncTask asyncTask;
	
	@RequestMapping("")
	public String doTask() throws InterruptedException{
		long currentTimeMillis = System.currentTimeMillis();
		Future<String> task1 = asyncTask.task1();
		Future<String> task2 = asyncTask.task2();
		Future<String> task3 = asyncTask.task3();
		String result = null;
		for (;;) {
			if(task1.isDone() && task2.isDone() && task3.isDone()) {
				// 三個任務都調用完成,退出循環等待
				break;
			}
			Thread.sleep(1000);
		}
		long currentTimeMillis1 = System.currentTimeMillis();
		result = "task任務總耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms";
		return result;
	}
}
           

1.4 配置參數詳解:

  1. id:當配置多個executor時,被@Async(“id”)指定使用;也被作為線程名的字首。
  2. core-size:最小的線程數,預設:1(該線程會一直存在)core-size:最小的線程數,預設:1(該線程會一直存在)
  3. max-size:最大的線程數,預設:Integer.MAX_VALUE(當線程數大于core-size+queue-capacity會建立最大線程,keep-alive設定該線程會被結束掉)max-size:最大的線程數,預設:Integer.MAX_VALUE(當線程數大于core-size+queue-capacity會建立最大線程,keep-alive設定該線程會被結束掉)
  4. queue-capacity:當最小的線程數已經被占用滿後,新的任務會被放進queue裡面,當這個queue的capacity也被占滿之後,pool裡面會建立新線程處理這個任務,直到總線程數達到了maxsize,這時系統會拒絕這個任務并抛出TaskRejectedException異常(預設配置的情況下,可以通過rejection-policy來決定如何處理這種情況)。預設值為:Integer.MAX_VALUEqueue-capacity:當最小的線程數已經被占用滿後,新的任務會被放進queue裡面,當這個queue的capacity也被占滿之後,pool裡面會建立新線程處理這個任務,直到總線程數達到了maxsize,這時系統會拒絕這個任務并抛出TaskRejectedException異常(預設配置的情況下,可以通過rejection-policy來決定如何處理這種情況)。預設值為:Integer.MAX_VALUE
  5. keep-alive:超過coresize的那些線程,任務完成後,再經過這個時長(秒)會被結束掉keep-alive:超過coresize的那些線程,任務完成後,再經過這個時長(秒)會被結束掉
  6. rejection-policy:當pool已經達到max size的時候,如何處理新任務rejection-policy:當pool已經達到max size的時候,如何處理新任務

    6.1. ABORT(預設):抛出TaskRejectedException異常,然後不執行6.1. ABORT(預設):抛出TaskRejectedException異常,然後不執行

    6.2. DISCARD:不執行,也不抛出異常

    6.3. DISCARD_OLDEST:丢棄queue中最舊的那個任務(會抛棄隊列中對開式進入的)

    6.4. CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行(會阻塞,等待所有core-size,queue-capacity,max-size執)