一.springboot開線程執行異步任務
1.Spring通過任務執行器TaskExecutor,來實現多線程和並發編程,使用ThreadPoolTaskExecutor可實現一個基於線程池的TaskExecutor;
2.異步需要在配置類上面加
@EnableAsync 來開啟對異步任務的支持在需要異步執行的方法上面加@Async 來聲明這個方法是一個需要異步執行的方法;
3.
讓配置類實現AsyncConfigurer接口,並重寫getAsyncExecutor方法,並返回一個ThreasPoolTaskExecutor,就可以獲取一個基於線程池的TaskExecutor;
4.
@Async 用在方法上,表示這個方法是一個異步的方法,如果用在類上面,表明這個類中的所有方法都是異步的方法。
(1).配置類
1 package com.yunzhangfang.springboot1.config; 2 3 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 4 import org.springframework.context.annotation.ComponentScan; 5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.scheduling.annotation.AsyncConfigurer; 7 import org.springframework.scheduling.annotation.EnableAsync; 8 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 9 10 import java.util.concurrent.Executor; 11 12 @Configuration 13 @ComponentScan("com.yunzhangfang.springboot1.service") 14 @EnableAsync 15 public class ThreadConfig implements AsyncConfigurer { 16 17 // ThredPoolTaskExcutor的處理流程 18 // 當池子大小小於corePoolSize,就新建線程,並處理請求 19 // 當池子大小等於corePoolSize,把請求放入workQueue中,池子里的空閑線程就去workQueue中取任務並處理 20 // 當workQueue放不下任務時,就新建線程入池,並處理請求,如果池子大小撐到了maximumPoolSize,就用RejectedExecutionHandler來做拒絕處理 21 // 當池子的線程數大於corePoolSize時,多余的線程會等待keepAliveTime長時間,如果無請求可處理就自行銷毀 22 @Override 23 public Executor getAsyncExecutor() { 24 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 25 executor.setCorePoolSize(5); 26 executor.setMaxPoolSize(15); 27 executor.setQueueCapacity(25); 28 executor.initialize(); 29 return executor; 30 } 31 32 @Override 33 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 34 return null; 35 } 36 37 }
(2).異步任務
1 package com.yunzhangfang.springboot1.service; 2 3 import org.springframework.scheduling.annotation.Async; 4 import org.springframework.scheduling.annotation.AsyncResult; 5 import org.springframework.stereotype.Service; 6 7 import java.util.concurrent.Future; 8 9 @Service 10 public class TaskService { 11 12 @Async 13 /** 14 * 表明是異步調用 15 * 沒有返回值 16 */ 17 public void excutVoidTask(int i) { 18 System.out.println("異步執行任務第[" + i + "] 個"); 19 } 20 21 /** 22 * 有返回值 23 * 異常調用 24 * 25 * @param i 26 * @return 27 * @throws InterruptedException 28 */ 29 @Async 30 public Future<String> excuteValueTask(int i) throws InterruptedException { 31 Thread.sleep(1000); 32 Future<String> future = new AsyncResult<String>("success is " + i); 33 System.out.println("異步執行任務第[" + i + "] 個"); 34 return future; 35 } 36 37 }
(3).測試異步任務
1 package com.yunzhangfang.springboot1; 2 3 import com.yunzhangfang.springboot1.service.TaskService; 4 import org.junit.Test; 5 import org.junit.runner.RunWith; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.boot.test.context.SpringBootTest; 8 import org.springframework.core.task.TaskRejectedException; 9 import org.springframework.test.context.junit4.SpringRunner; 10 11 import java.util.ArrayList; 12 import java.util.List; 13 import java.util.concurrent.ExecutionException; 14 import java.util.concurrent.Future; 15 16 @RunWith(SpringRunner.class) 17 @SpringBootTest 18 public class Springboot1ApplicationTests { 19 20 @Autowired 21 private TaskService service; 22 23 @Test 24 public void contextLoads() { 25 } 26 27 /** 28 * 沒有返回值測試 29 */ 30 @Test 31 public void testVoid() { 32 for (int i = 0; i < 20; i++) { 33 service.excutVoidTask(i); 34 } 35 System.out.println("========主線程執行完畢========="); 36 } 37 38 @Test 39 public void testReturn() throws InterruptedException, ExecutionException { 40 List<Future<String>> lstFuture = new ArrayList<>();// 存放所有的線程,用於獲取結果 41 for (int i = 0; i < 100; i++) { 42 while (true) { 43 try { 44 // 線程池超過最大線程數時,會拋出TaskRejectedException,則等待1s,直到不拋出異常為止 45 Future<String> stringFuture = service.excuteValueTask(i); 46 lstFuture.add(stringFuture); 47 break; 48 } catch (TaskRejectedException e) { 49 System.out.println("線程池滿,等待1S。"); 50 Thread.sleep(1000); 51 } 52 } 53 } 54 55 // 獲取值.get是阻塞式,等待當前線程完成才返回值 56 for (Future<String> future : lstFuture) { 57 System.out.println(future.get()); 58 } 59 60 System.out.println("========主線程執行完畢========="); 61 } 62 63 }
有錯誤,希望指出,共同進步,天天向上