Spring通過任務執行器(TaskExecutor)來實現多線程和並發編程。使用ThreadPoolTaskExecutor可實現一個基於線程池的TaskExecutor。而實際開發中任務一般是非阻礙的,即異步的,所以我們要在配置類中通過@EnableAsync開啟對異步任務的支持,並通過在實際執行的Bean的方法中使用@Async注解聲明其是一個異步任務。
配置類
package com.gxr.imybatisplus.service.Thread; 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; import java.util.concurrent.Executor; /** * @Description: 配置類實現AsyncConfigurer接口,並重寫getAsyncExecutor方法,並返回一個ThreadPoolTaskExecutor, * 這樣我們就獲得一個基於線程池TaskExecutor - 基於Spring配置方式 * */ @Configuration @ComponentScan("com.gxr.imybatisplus.service.Thread") @EnableAsync public class CustomMultiThreadingConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //如果池中的實際線程數小於corePoolSize,無論是否其中有空閑的線程,都會給新的任務產生新的線程 taskExecutor.setCorePoolSize(5); //queueCapacity 線程池所使用的緩沖隊列 taskExecutor.setQueueCapacity(256); //連接池中保留的最大連接數。 taskExecutor.setMaxPoolSize(1024); //線程名稱前綴 taskExecutor.setThreadNamePrefix("Application Thread-"); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler(); } }
多線程任務
package com.gxr.imybatisplus.service.Thread; import com.gxr.imybatisplus.entity.TSampleE; import com.gxr.imybatisplus.mapper.SampleEMapper; import com.gxr.imybatisplus.utils.GenObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.List; import java.util.logging.Logger; /** * @Description: 創建線程任務服務 - 基於Spring方式 */ @Service public class CustomMultiThreadingService { private final Logger logger = Logger.getLogger(this.getClass().getName()); @Autowired SampleEMapper sampleMapper; @Async public void insertOne(String tableName) { // sampleMapper = ApplicationContextProvider.getBean(SampleEMapper.class); int id = getNextId(tableName); TSampleE sample = GenObject.genSampleObj(id, tableName); sampleMapper.insertOne(sample); // logger.info(tableName + "插入成功!"); } @Async public void insertBatch(String tableName, int number) { // sampleMapper = ApplicationContextProvider.getBean(SampleEMapper.class); int id = getNextId(tableName); List<TSampleE> sampleList = GenObject.getSampleList(id, number, tableName); sampleMapper.insertList(sampleList, tableName); logger.info(tableName + "插入成功!總共" + number + "條"); } /** * 獲取當前最大id值 */ private int getMaxId(String tableName) { int id; try { id = sampleMapper.getMaxID(tableName); } catch (NullPointerException e) { return 0; } return id; } /** * 獲取下一條數據的id值 */ public int getNextId(String tableName) { return getMaxId(tableName) + 1; } }
測試執行
package com.gxr.imybatisplus.threadTest; import com.gxr.imybatisplus.service.Thread.CustomMultiThreadingService; import com.gxr.imybatisplus.service.Thread.MyThreadService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class ThreadTest { @Autowired CustomMultiThreadingService multiThreadingService; /** * 多線程測試 - 實現Runnable接口方式 */ @Test public void testThread() { String[] tableNames = {"t_sample_s_pg1", "t_sample_s_pg2"}; int number = 20; for (String name : tableNames) { new Thread(new MyThreadService(name, number)).start(); } } /** * 多線程測試 - 基於Spring配置方式 */ @Test public void testThread_spring() { String[] tableNames = {"t_sample_s_pg1", "t_sample_s_pg2"}; int number = 20; for (String name : tableNames) { multiThreadingService.insertBatch(name, number); } } }
參考文獻:
https://www.cnblogs.com/onlymate/p/9686740.html
https://zhuanlan.zhihu.com/p/134636915