多線程
Spring通過任務執行器(TaskExecutor)來實現多線程和並發編程。使用ThreadPoolTaskExecutor可實現一個基於線程池的TaskExecutor。而實際開發中任務一般是非阻礙的,即異步的,所以我們要在配置類中通過@EnableAsync開啟對異步任務的支持,並通過在實際執行的Bean的方法中使用@Async注解聲明其是一個異步任務。
此外,還提供一種Java的實現方式,多種方式去嘗試如何去實現多線程。
實現
一、基於Spring
1、配置類
import java.util.concurrent.Executor; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * @Description: 配置類實現AsyncConfigurer接口,並重寫getAsyncExecutor方法,並返回一個ThreadPoolTaskExecutor, * 這樣我們就獲得一個基於線程池TaskExecutor * @ClassName: CustomMultiThreadingConfig * @Author: OnlyMate * @Date: 2018年9月21日 下午2:50:14 */ @Configuration @ComponentScan("com.only.mate.springboot.multithreading") @EnableAsync//利用@EnableAsync注解開啟異步任務支持 public class CustomMultiThreadingConfig implements AsyncConfigurer{ @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler(); } }
2、創建線程任務
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * @Description: 創建線程任務服務 * @ClassName: CustomMultiThreadingService * @Author: OnlyMate * @Date: 2018年9月21日 下午3:17:57 */ @Service public class CustomMultiThreadingService { private Logger logger = LoggerFactory.getLogger(CustomMultiThreadingService.class); /** * @Description:通過@Async注解表明該方法是一個異步方法, * 如果注解在類級別上,則表明該類所有的方法都是異步方法,而這里的方法自動被注入使用ThreadPoolTaskExecutor作為TaskExecutor * @Title: executeAysncTask1 * @Date: 2018年9月21日 下午2:54:32 * @Author: OnlyMate * @Throws * @param i */ @Async public void executeAysncTask1(Integer i){ logger.info("CustomMultiThreadingService ==> executeAysncTask1 method: 執行異步任務{} ", i); } /** * @Description:通過@Async注解表明該方法是一個異步方法, * 如果注解在類級別上,則表明該類所有的方法都是異步方法,而這里的方法自動被注入使用ThreadPoolTaskExecutor作為TaskExecutor * @Title: executeAsyncTask2 * @Date: 2018年9月21日 下午2:55:04 * @Author: OnlyMate * @Throws * @param i */ @Async public void executeAsyncTask2(Integer i){ logger.info("CustomMultiThreadingService ==> executeAsyncTask2 method: 執行異步任務{} ", i); } }
3、觸發線程任務
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.only.mate.springboot.multithreading.CustomMultiThreadingService; /** * @Description:自定義多線程Controller * @ClassName: CustomMultiThreadingController * @Author: OnlyMate * @Date: 2018年9月21日 下午3:02:49 */ @Controller @RequestMapping(value="/multithreading") public class CustomMultiThreadingController { @Autowired private CustomMultiThreadingService customMultiThreadingService; @ResponseBody @RequestMapping(value="/dotask") public String doTask() { for (int i=0;i<10;i++){ customMultiThreadingService.executeAysncTask1(i); customMultiThreadingService.executeAsyncTask2(i); } return "success"; } }
4、效果圖
訪問http://localhost:8088/springboot/multithreading/dotask
二、基於Java
1、異步線程調度管理器
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * @Description: 異步線程調度管理器 * @ClassName: CustomAsyncScheduler * @Author: OnlyMate * @Date: 2018年9月21日 下午3:25:40 */ public class CustomAsyncScheduler { private volatile static CustomAsyncScheduler instance; private static ThreadPoolExecutor chnlBackendQueryPool; private CustomAsyncScheduler() { } @SuppressWarnings({ "rawtypes", "static-access", "unchecked" }) public static CustomAsyncScheduler getInstance() { if (instance == null) { synchronized (CustomAsyncScheduler.class) { if (instance == null) { instance = new CustomAsyncScheduler(); BlockingQueue queue = new LinkedBlockingQueue(); chnlBackendQueryPool = new ThreadPoolExecutor(50, 100, 30, TimeUnit.SECONDS, queue); chnlBackendQueryPool.allowCoreThreadTimeOut(true); instance.setChnlBackendQueryPool(chnlBackendQueryPool); } } } return instance; } public ThreadPoolExecutor getChnlBackendQueryPool() { return chnlBackendQueryPool; } public static void setChnlBackendQueryPool(ThreadPoolExecutor chnlBackendQueryPool) { CustomAsyncScheduler.chnlBackendQueryPool = chnlBackendQueryPool; } public static void setInstance(CustomAsyncScheduler instance) { CustomAsyncScheduler.instance = instance; } }
2、創建線程任務
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * @Description: 創建線程任務服務 * @ClassName: CustomMultiThreadingService * @Author: OnlyMate * @Date: 2018年9月21日 下午3:17:57 */ @Service public class CustomMultiThreadingService { private Logger logger = LoggerFactory.getLogger(CustomMultiThreadingService.class); /** * @Description:通過@Async注解表明該方法是一個異步方法, * 如果注解在類級別上,則表明該類所有的方法都是異步方法,而這里的方法自動被注入使用ThreadPoolTaskExecutor作為TaskExecutor * @Title: executeAysncTask1 * @Date: 2018年9月21日 下午2:54:32 * @Author: OnlyMate * @Throws * @param i */ @Async public void executeAysncTask1(Integer i){ logger.info("CustomMultiThreadingService ==> executeAysncTask1 method: 執行異步任務{} ", i); } /** * @Description:通過@Async注解表明該方法是一個異步方法, * 如果注解在類級別上,則表明該類所有的方法都是異步方法,而這里的方法自動被注入使用ThreadPoolTaskExecutor作為TaskExecutor * @Title: executeAsyncTask2 * @Date: 2018年9月21日 下午2:55:04 * @Author: OnlyMate * @Throws * @param i */ @Async public void executeAsyncTask2(Integer i){ logger.info("CustomMultiThreadingService ==> executeAsyncTask2 method: 執行異步任務{} ", i); } /** * @Description: 異步線程調度管理器創建線程任務 * @Title: executeAsyncTask3 * @Date: 2018年9月21日 下午3:32:28 * @Author: OnlyMate * @Throws * @param i */ public void executeAsyncTask3(Integer i){ CustomAsyncScheduler.getInstance().getChnlBackendQueryPool().execute(new Runnable() { @Override public void run() { logger.info("CustomMultiThreadingService ==> executeAsyncTask3 method: 執行異步任務{} ", i); } }); } }
3、觸發線程任務
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.only.mate.springboot.multithreading.CustomMultiThreadingService; /** * @Description:自定義多線程Controller * @ClassName: CustomMultiThreadingController * @Author: OnlyMate * @Date: 2018年9月21日 下午3:02:49 */ @Controller @RequestMapping(value="/multithreading") public class CustomMultiThreadingController { @Autowired private CustomMultiThreadingService customMultiThreadingService; @ResponseBody @RequestMapping(value="/dotask") public String doTask() { for (int i=0;i<10;i++){ customMultiThreadingService.executeAysncTask1(i); customMultiThreadingService.executeAsyncTask2(i); } return "success"; } @ResponseBody @RequestMapping(value="/dojob") public String doJob() { for (int i=0;i<10;i++){ customMultiThreadingService.executeAysncTask1(i); customMultiThreadingService.executeAsyncTask2(i); customMultiThreadingService.executeAsyncTask3(i); } return "success"; } }
4、效果圖
訪問http://localhost:8088/springboot/multithreading/dojob