Java给多线程编程提供了内置的支持。,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务,能满足程序员编写高效率的程序来达到充分利用 CPU 的目的,实现多线程的方法有四种,继承Thread类,实现Runable接口,Callable接口,或者从线程池中获取。
先了解线程的生命周期
线程池的优点
Java通过Executors提供五种线程池
@Configuration
public class GlobalConfig {
/**
* 默认线程池线程池
*
* @return Executor
*/
@Bean
public ThreadPoolTaskExecutor defaultThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数目
executor.setCorePoolSize(16);
//指定最大线程数
executor.setMaxPoolSize(64);
//队列中最大的数目
executor.setQueueCapacity(16);
//线程名称前缀
executor.setThreadNamePrefix("defaultThreadPool_");
//rejection-policy:当pool已经达到max size的时候,如何处理新任务
//CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
//对拒绝task的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//线程空闲后的最大存活时间
executor.setKeepAliveSeconds(60);
//加载
executor.initialize();
return executor;
}
//通过注解引入配置
@Resource(name = "defaultThreadPool")
private ThreadPoolTaskExecutor executor;
@ApiOperation(value = "批量给用户发短信")
@PostMapping("/sendMessage")
@Unchecked
public ResultWrapper sendMessage(@ApiParam(required = true, value = "电话集合") @RequestParam List<String> phones) {
try {
if (CollUtil.isNotEmpty(phones)) {
List<List<String>> split = CollUtil.split(phones, 3);
for (List<String> list : split) {
List<Future> futures = new ArrayList<>();
for (String phone : list) {
Future<?> future = executor.submit(() -> {
//发送短信
System.out.println("给" + phone + "发送短信");
});
futures.add(future);
}
//阻塞等待批量执行结果然后再执行下一个批次
for (Future future : futures) {
while (true) {//CPU高速轮询:每个future都并发轮循,判断完成状态然后获取结果,这一行,是本实现方案的精髓所在。即有10个future在高速轮询,完成一个future的获取结果,就关闭一个轮询
if (future.isDone()) {//获取future成功完成状态
break;
} else {
ThreadUtil.sleep(100);//每次轮询休息1毫秒(CPU纳秒级),避免CPU高速轮循耗空CPU
}
}
}
System.out.println("成功发送3个");
}
}
} catch (Exception e) {
e.printStackTrace();
return ResultWrapper.error().putData("发送失败");
}
return ResultWrapper.ok().putData("发送成功");
}
结果如下