目录
线程池
线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。
全局线程池
对于SpringBoot来说,配置全局线程池还是非常方便的,加入一下配置初始化一个线程池
@Configuration
@EnableAsync
public class ExecutorConfig {
@Bean("new_Thread")
public Executor carSocketExecutor() {
//获取当前机器的核数
int cpuNum = Runtime.getRuntime().availableProcessors();
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(cpuNum);
//配置最大线程数
executor.setMaxPoolSize(cpuNum * 2);
//配置队列大小
executor.setQueueCapacity(100);
//线程存活时间
executor.setKeepAliveSeconds(60);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("new_Thread");
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
这里测试的实在其有返回值的情况下,返回值类型为Future,@Async注解表示该方法从线程池中获取线程来执行,其中线程池名称为非必填
@Override
@Async("new_Thread")
public Future<String> testService01() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("test01执行完毕!");
}
@Override
@Async("new_Thread")
public Future<String> testService02() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("test02执行完毕!");
}
@Override
@Async("new_Thread")
public Future<String> testService03() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("test03执行完毕!");
}
测试方法,因为是多线程的原因,主线程不会等待每一个方法的返回值,所以先将返回值结果统一放进一个集合中,直到所有方法都开始执行后在对其进行遍历,Future中的get()方法可以获取到真正的返回值,只有调用了这个方法,主线程才会等待方法中的结果返回
@GetMapping("/test01")
public StringBuilder test01() {
//返回结果集
List<Future<String>> results = new ArrayList<>();
//响应结果
StringBuilder restStr = new StringBuilder();
//开始时间
Long startTime = System.currentTimeMillis();
results.add(multithreadingService.testService01());
results.add(multithreadingService.testService02());
results.add(multithreadingService.testService03());
for (Future<String> result : results) {
try {
restStr.append(result.get()).append("\n");
} catch (Exception e) {
e.printStackTrace();
}
}
//结束时间
Long endTime = System.currentTimeMillis();
restStr.append("共用时").append(endTime - startTime).append("ms");
return restStr;
}
查看测试结果,可以看到三个方法共用时大约10s钟,开头我给每个方法的执行时间都设置的10s,所以 此次测试是成功的!
局部线程池
创建局部线程池可以使用Executors类中的方法来实现,本文中演示创建为一个固定长度的线程池
测试方法跟前面的全局线程池一样
@Override
public String testService04() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "test04执行完毕!";
}
@Override
public String testService05() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "test05执行完毕!";
}
@Override
public String testService06() {
try {
System.out.println("线程名称 " + Thread.currentThread().getName());
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "test06执行完毕!";
}
@GetMapping("/test02")
public StringBuilder test02() {
//返回结果集
List<Future<String>> results = new ArrayList<>();
//响应结果
StringBuilder restStr = new StringBuilder();
//开始时间
Long startTime = System.currentTimeMillis();
//创建一个固定长度的线程池(表示最大并发量为3,队列超过3则等待)
ExecutorService executorService = Executors.newFixedThreadPool(POOL_COUNT, new MyThreadFactory("my_thread"));
results.add(executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.interrupted();
return multithreadingService.testService04();
}
}));
results.add(executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.interrupted();
return multithreadingService.testService05();
}
}));
results.add(executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.interrupted();
return multithreadingService.testService06();
}
}));
for (Future<String> result : results) {
try {
restStr.append(result.get()).append("\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
executorService.shutdown();
}
}
//结束时间
Long endTime = System.currentTimeMillis();
restStr.append("共用时").append(endTime - startTime).append("ms");
return restStr;
}
线程工厂这里主要是给线程起一个名字,另外还可以根据业务需求加入一些线程的创建时间,结束时间等日志信息在其中
@Data
public class MyThreadFactory implements ThreadFactory {
//线程名称
private String poolName;
//线程编号
private int threadCount;
public MyThreadFactory(String poolName) {
this.poolName = poolName;
threadCount = 0;
}
@Override
public Thread newThread(Runnable runnable) {
threadCount++;
return new Thread(runnable, poolName + "_" +threadCount);
}
测试结果