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 配置參數詳解:
- id:當配置多個executor時,被@Async(“id”)指定使用;也被作為線程名的字首。
- core-size:最小的線程數,預設:1(該線程會一直存在)core-size:最小的線程數,預設:1(該線程會一直存在)
- max-size:最大的線程數,預設:Integer.MAX_VALUE(當線程數大于core-size+queue-capacity會建立最大線程,keep-alive設定該線程會被結束掉)max-size:最大的線程數,預設:Integer.MAX_VALUE(當線程數大于core-size+queue-capacity會建立最大線程,keep-alive設定該線程會被結束掉)
- 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
- keep-alive:超過coresize的那些線程,任務完成後,再經過這個時長(秒)會被結束掉keep-alive:超過coresize的那些線程,任務完成後,再經過這個時長(秒)會被結束掉
-
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執)