@(多线程&&并发)
多线程异步任务处理
欢迎关注作者简书
csdn传送门
我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,那我们怎么去使用它呢?我们先来了解下什么是线程池?
线程池
线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。线程池中线程的数量通常完全取决于可用内存数量和应用程序的需求。然而,增加可用线程数量是可能的。线程池中的每个线程都有被分配一个任务,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。
线程池的优缺点
使用线程池管理线程的优点:
- 线程的创建和销毁由线程池维护,一个线程在完成任务后并不会立即销毁,而是由后续的任务复用这个线程,从而减少线程的创建和销毁,节约系统的开销
- 线程池旨在线程的复用,这就可以节约我们用以往的方式创建线程和销毁所消耗的时间,减少线程频繁调度的开销,从而节约系统资源,提高系统吞吐量
- 在执行大量异步任务时提高了性能
- Java内置的一套ExecutorService线程池相关的api,可以更方便的控制线程的最大并发数、线程的定时任务、单线程的顺序执行等
常用的线程池技术
- Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务。
- Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程。
- Executors.newScheduledThreadPool(int n):创建一个定长线程池,支持定时及周期性任务执行。
- Executors.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
@Async注解
在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
如何在Spring中启用@Async。基于Java配置的启用方式:
@Configuration
@EnableAsync
public class ExecutorConfig {
}
源码
配置类:
/**
* @program:
* @description: 线程池配置类
* @author: zhouzhixiang
* @create: 2018-11-07 19:10
*/
@Configuration
@EnableAsync
public class ExecutorConfig {
@Bean
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(20);
//配置最大线程数
executor.setMaxPoolSize(20);
//配置队列大小
executor.setQueueCapacity(99999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("async-service-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
接口:
/**
* @program:
* @description: 异步接口
* @author: zhouzhixiang
* @create: 2018-11-07 19:08
*/
public interface AsyncService {
public void testAsync();
}
实现类:
/**
* @program:
* @description:
* @author: zhouzhixiang
* @create: 2018-11-07 19:08
*/
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
@Async("asyncServiceExecutor")
public void testAsync() {
try{
Thread.sleep(10000);
logger.info("start executeAsync");
System.out.println("测试异步任务!");
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("end executeAsync");
}
}
controller:
@ApiOperation(value = "business-测试", notes = "business-测试")
@PostMapping("test")
public ServiceResponse test2(@RequestBody JSONObject jsonObject, HttpServletRequest req){
businessService.test();
ServiceResponse response = new ServiceResponse();
response.setCode(200);
response.setData("成功");
return response;
}
控制台输出:
由下图可以看出,异步任务执行成功。
欢迎加入Java猿社区
网友评论