-
corePoolSize(核心線程數(shù))
- 核心線程會一直存在择镇,即使沒有任務(wù)執(zhí)行娇斩;
- 當線程數(shù)小于核心線程數(shù)的時候部念,即使有空閑線程,也會一直創(chuàng)建線程直到達到核心線程數(shù)土榴;
- 設(shè)置allowCoreThreadTimeout=true(默認false)時诀姚,核心線程會超時關(guān)閉。
-
queueCapacity(任務(wù)隊列容量)
- 也叫阻塞隊列玷禽,當核心線程都在運行赫段,此時再有任務(wù)進來,會進入任務(wù)隊列矢赁,排隊等待線程執(zhí)行糯笙。
-
maxPoolSize(最大線程數(shù))
- 線程池里允許存在的最大線程數(shù)量;
- 當任務(wù)隊列已滿撩银,且線程數(shù)量大于等于核心線程數(shù)時给涕,會創(chuàng)建新的線程執(zhí)行任務(wù);
- 線程池里允許存在的最大線程數(shù)量额获。當任務(wù)隊列已滿够庙,且線程數(shù)量大于等于核心線程數(shù)時,會創(chuàng)建新的線程執(zhí)行任務(wù)抄邀。
-
keepAliveTime(線程空閑時間)
- 當線程空閑時間達到keepAliveTime時耘眨,線程會退出(關(guān)閉),直到線程數(shù)等于核心線程數(shù)境肾;
- 如果設(shè)置了allowCoreThreadTimeout=true剔难,則線程會退出直到線程數(shù)等于零胆屿。
- allowCoreThreadTimeout(允許核心線程超時)
- ejectedExecutionHandler(任務(wù)拒絕處理器)
- 當線程數(shù)量達到最大線程數(shù),且任務(wù)隊列已滿時,會拒絕任務(wù);
- 調(diào)用線程池shutdown()方法后吱肌,會等待執(zhí)行完線程池的任務(wù)之后奔垦,再shutdown()。如果在調(diào)用了shutdown()方法和線程池真正shutdown()之間提交任務(wù)砰识,會拒絕新任務(wù)。
-
任務(wù)執(zhí)行解析
- 如果線程池中線程數(shù)量 < 核心線程數(shù),新建一個線程執(zhí)行任務(wù)唇兑;
- 如果線程池中線程數(shù)量 >= 核心線程數(shù),則將任務(wù)放入任務(wù)隊列
- 如果線程池中線程數(shù)量 >= 核心線程數(shù) 且 < maxPoolSize,且任務(wù)隊列滿了桦锄,則創(chuàng)建新的線程扎附;
- 如果線程池中線程數(shù)量 > 核心線程數(shù),當線程空閑時間超過了keepalive時,則會銷毀線程结耀;由此可見線程池的隊列如果是無界隊列留夜,那么設(shè)置線程池最大數(shù)量是無效的;
- 如果線程池中的任務(wù)隊列滿了图甜,而且線程數(shù)達到了maxPoolSize碍粥,并且沒有空閑的線程可以執(zhí)行新的任務(wù),這時候再提交任務(wù)就會執(zhí)行拒絕策略
-
rejectedExecutionHandler字段用于配置拒絕策略黑毅,常用的拒絕策略如下:
- AbortPolicy 拋出RejectedExecutionException嚼摩。
- CallerRunsPolicy 直接在execute方法的調(diào)用線程中運行被拒絕的任務(wù)。
- DiscardOldestPolicy 放棄最舊的未處理請求矿瘦,然后重試execute枕面。
- DiscardPolicy 下它將丟棄被拒絕的任務(wù)。
Spring Boot中異步線程池的配置
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@Configuration
public class AsyncExecutorConfig {
@Bean
public Executor asyncServiceExecutor() {
log.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心線程數(shù)
//如果是IO密集型應用缚去,則線程池大小設(shè)置為2N+1潮秘;
//如果是CPU密集型應用,則線程池大小設(shè)置為N+1易结;
executor.setCorePoolSize(6);
//配置最大線程數(shù)
executor.setMaxPoolSize(10);
//配置隊列大小
executor.setQueueCapacity(10000);
//配置線程池中的線程的名稱前綴
executor.setThreadNamePrefix("async-service-");
// 設(shè)置拒絕策略:當pool已經(jīng)達到max size的時候唇跨,如何處理新任務(wù)
// CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//執(zhí)行初始化
executor.initialize();
return executor;
}
}
異步使用方法
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class AsyncService {
@Async("asyncServiceExecutor")
public Future<String> getAsyncResult1() {
String result = "asyncResultTest1";
try {
Thread.sleep(3000);
log.info("線程名稱:{}衬衬,睡眠:{}秒", Thread.currentThread().getName(), "3");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>(result);
}
@Async("asyncServiceExecutor")
public Future<String> getAsyncResult2() {
String result = "asyncResultTest2";
try {
Thread.sleep(4000);
log.info("線程名稱:{}买猖,睡眠:{}秒", Thread.currentThread().getName(), "4");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>(result);
}
}
@RestController
@RequestMapping(value = "/test")
public class TestController extends BaseBeanController {
//線程池,上面Config中定義的
@Autowired
public Executor asyncServiceExecutor;
@PostMapping(value = "/test")
public DeferredResult<R> test() throws ExecutionException, InterruptedException {
DeferredResult deferredResult = new DeferredResult(10000L);
CompletableFuture<R> result = CompletableFuture.supplyAsync(() -> {
//耗時方法
}, asyncServiceExecutor);
deferredResult.setResult(result.get());
return deferredResult;
}
}