多執行緒非同步任務處理
阿新 • • 發佈:2018-12-01
@(多執行緒&&併發)
多執行緒非同步任務處理
歡迎關注作者部落格
簡書傳送門
文章目錄
我們常用ThreadPoolExecutor提供的執行緒池服務,springboot框架提供了@Async註解,那我們怎麼去使用它呢?我們先來了解下什麼是執行緒池?
執行緒池
執行緒池是指在初始化一個多執行緒應用程式過程中建立一個執行緒集合,然後在需要執行新的任務時重用這些執行緒而不是新建一個執行緒。執行緒池中執行緒的數量通常完全取決於可用記憶體數量和應用程式的需求。然而,增加可用執行緒數量是可能的。執行緒池中的每個執行緒都有被分配一個任務,一旦任務已經完成了,執行緒回到池子中並等待下一次分配任務。
執行緒池的優缺點
使用執行緒池管理執行緒的優點:
- 執行緒的建立和銷燬由執行緒池維護,一個執行緒在完成任務後並不會立即銷燬,而是由後續的任務複用這個執行緒,從而減少執行緒的建立和銷燬,節約系統的開銷
- 執行緒池旨線上程的複用,這就可以節約我們用以往的方式建立執行緒和銷燬所消耗的時間,減少執行緒頻繁排程的開銷,從而節約系統資源,提高系統吞吐量
- 在執行大量非同步任務時提高了效能
- Java內建的一套ExecutorService執行緒池相關的api,可以更方便的控制執行緒的最大併發數、執行緒的定時任務、單執行緒的順序執行等
常用的執行緒池技術
- Executors.newCacheThreadPool():可快取執行緒池,先檢視池中有沒有以前建立的執行緒,如果有,就直接使用。如果沒有,就建一個新的執行緒加入池中,快取型池子通常用於執行一些生存期很短的非同步型任務。
- Executors.newFixedThreadPool(int n):建立一個可重用固定個數的執行緒池,以共享的無界佇列方式來執行這些執行緒。
- Executors.newScheduledThreadPool(int n):建立一個定長執行緒池,支援定時及週期性任務執行。
- Executors.newSingleThreadExecutor():建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
@Async註解
在Spring中,基於@Async標註的方法,稱之為非同步方法;這些方法將在執行的時候,將會在獨立的執行緒中被執行,呼叫者無需等待它的完成,即可繼續其他的操作。
如何在Spring中啟用@Async。基於Java配置的啟用方式:
@Configuration
@EnableAsync
public class ExecutorConfig {
}
原始碼
配置類:
/**
* @program:
* @description: 執行緒池配置類
* @author: zhouzhixiang
* @create: 2018-11-07 19:10
*/
@Configuration
@EnableAsync
public class ExecutorConfig {
@Bean
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心執行緒數
executor.setCorePoolSize(20);
//配置最大執行緒數
executor.setMaxPoolSize(20);
//配置佇列大小
executor.setQueueCapacity(99999);
//配置執行緒池中的執行緒的名稱字首
executor.setThreadNamePrefix("async-service-");
// rejection-policy:當pool已經達到max size的時候,如何處理新任務
// CALLER_RUNS:不在新執行緒中執行任務,而是有呼叫者所在的執行緒來執行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//執行初始化
executor.initialize();
return executor;
}
}
介面:
/**
* @program:
* @description: 非同步介面
* @author: zhouzhixiang
* @create: 2018-11-07 19:08
*/
public interface AsyncService {
public void testAsync();
}
實現類:
/**
* @program:
* @description:
* @author: zhouzhixiang
* @create: 2018-11-07 19:08
*/
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
@Async("asyncServiceExecutor")
public void testAsync() {
try{
Thread.sleep(10000);
logger.info("start executeAsync");
System.out.println("測試非同步任務!");
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("end executeAsync");
}
}
controller:
@ApiOperation(value = "business-測試", notes = "business-測試")
@PostMapping("test")
public ServiceResponse test2(@RequestBody JSONObject jsonObject, HttpServletRequest req){
businessService.test();
ServiceResponse response = new ServiceResponse();
response.setCode(200);
response.setData("成功");
return response;
}
控制檯輸出:
由下圖可以看出,非同步任務執行成功。
歡迎加入Java猿社群