SpringBoot自定义线程池处理异步任务
@Async异步调用
就不解释什么是异步调用了,Spring Boot中进行异步调用很简单
1.通过使用@Async注解就能简单的将原来的同步函数变为异步函数
package com.winner.service; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit; /**
* @author winner_0715
* @date 2018/12/06
*/
@Service
public class TaskServer { @Async
public void doTaskA() throws InterruptedException {
System.out.println("TaskA thread name->" + Thread.currentThread().getName());
Long startTime = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2); Long endTime = System.currentTimeMillis();
System.out.println("TaskA 耗时:" + (endTime - startTime));
} @Async
public void doTaskB() throws InterruptedException {
System.out.println("TaskB thread name->" + Thread.currentThread().getName());
Long startTime = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2);
Long endTime = System.currentTimeMillis();
System.out.println("TaskB耗时:" + (endTime - startTime));
}
}
为了让@Async注解能够生效,还需要在Spring Boot的主程序中配置@EnableAsync,如下所示:
package com.winner; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @author winner_0715
* @date 2018/12/06
*/
@SpringBootApplication
@EnableAsync
public class SpringBootAsyncApplication { public static void main(String[] args) {
SpringApplication.run(SpringBootAsyncApplication.class, args);
} }
注: @Async所修饰的函数不要定义为static类型,这样异步调用不会生效
测试
package com.winner.web; import com.winner.service.TaskServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /**
* @author winner_0715
* @description:
* @date 2018/12/6
*/
@RestController
public class HelloController { @Resource
private TaskServer taskServer; @GetMapping("/async")
public String testAsync() throws Exception {
System.out.println("主线程 name -->" + Thread.currentThread().getName());
taskServer.doTaskA();
taskServer.doTaskB();
return "Hello World";
}
}
任务线程和主线程的名称不同,表明是异步执行的!
自定义线程池
前面介绍使用@Async注解来实现异步调用了。对于这些异步执行的控制是我们保障自身应用健康的基本技能。下面介绍通过自定义线程池的方式来控制异步调用的并发。
定义线程池
第一步,定义一个线程池,比如:
package com.winner.threadpool; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; /**
* @author winner_0715
*/
@Configuration
public class ThreadPoolExecutorConfig {
private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1;
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
// -%d不要少
.setNameFormat("async-task-name-%d")
.setDaemon(true)
.build(); @Bean("taskExecutor")
public Executor taskExecutor() {
return new ThreadPoolExecutor(THREADS, 2 * THREADS,
5, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1024),
threadFactory, (r, executor) -> {
// 打印日志,添加监控等
System.out.println("task is rejected!");
});
}
}
上面我们通过使用ThreadPoolExecutor创建了一个线程池
使用线程池
在定义了线程池之后,我们如何让异步调用的执行任务使用这个线程池中的资源来运行呢?方法非常简单,我们只需要在@Async注解中指定线程池名即可,比如:
package com.winner.service; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit; /**
* @author winner_0715
* @date 2018/12/06
*/
@Service
public class TaskServer { @Async("taskExecutor")
public void doTaskA() throws InterruptedException {
System.out.println("MsgServer send A thread name->" + Thread.currentThread().getName());
Long startTime = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2); Long endTime = System.currentTimeMillis();
System.out.println("MsgServer send A 耗时:" + (endTime - startTime));
} @Async("taskExecutor")
public void doTaskB() throws InterruptedException {
System.out.println("MsgServer send B thread name->" + Thread.currentThread().getName());
Long startTime = System.currentTimeMillis();
TimeUnit.SECONDS.sleep(2);
Long endTime = System.currentTimeMillis();
System.out.println("MsgServer send B耗时:" + (endTime - startTime));
}
}
测试
package com.winner.web; import com.winner.service.TaskServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /**
* @author winner_0715
* @description:
* @date 2018/12/6
*/
@RestController
public class HelloController { @Resource
private TaskServer taskServer; @GetMapping("/async")
public String testAsync() throws Exception {
System.out.println("主线程 name -->" + Thread.currentThread().getName());
taskServer.doTaskA();
taskServer.doTaskB();
return "Hello World";
}
}
测试结果:
主线程 name -->http-nio-8080-exec-1
MsgServer send A thread name->async-task-name-0
MsgServer send B thread name->async-task-name-1
MsgServer send A 耗时:2001
MsgServer send B耗时:2001
SpringBoot自定义线程池处理异步任务的更多相关文章
- spring boot / cloud (四) 自定义线程池以及异步处理@Async
spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...
- spring boot自定义线程池以及异步处理
spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...
- SpringBoot 自定义线程池
本教程目录: 自定义线程池 配置spring默认的线程池 1. 自定义线程池 1.1 修改application.properties task.pool.corePoolSize=20 task.p ...
- SpringBoot 自定义线程池,多线程
原文:https://www.jianshu.com/p/832f2b162450 我们都知道spring只是为我们简单的处理线程池,每次用到线程总会new 一个新的线程,效率不高,所以我们需要自定义 ...
- SpringBoot—自定义线程池及并发定时任务模板
介绍 在项目开发中,经常遇到定时任务,今天通过自定义多线程池总结一下SpringBoot默认实现的定时任务机制. 定时任务模板 pom依赖 <dependencies> <dep ...
- Spring Boot使用@Async实现异步调用:自定义线程池
前面的章节中,我们介绍了使用@Async注解来实现异步调用,但是,对于这些异步执行的控制是我们保障自身应用健康的基本技能.本文我们就来学习一下,如果通过自定义线程池的方式来控制异步调用的并发. 定义线 ...
- 转载-SpringBoot结合线程池解决多线程问题实录;以及自己的总结
原文地址:https://blog.csdn.net/GFJ0814/article/details/92422245 看看这篇文章(继续学习):https://www.jianshu.com/p/3 ...
- Android线程管理之ThreadPoolExecutor自定义线程池
前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
随机推荐
- mace
作者:十岁的小男孩 QQ:929994365 心之安处即是吾乡. 本文主要的方向是终端移植.其主要又分两个小方向,理论和实践,即模型优化和模型移植.下文为前期写的,较为潦草,现在基本框架思路已经搭起来 ...
- PHP获取数组最后一个元素的键和值
<?php /** * PHP获取数组中最后一个元素下标和值 */ $arr = ['1' => 'name', '3' => 2, 5 => 6, 'name' => ...
- 使用css3美化复选框
声明:文章为转载(略改动),点击查看原文.如有侵权24小时内删除,联系QQ:1522025433. 我们知道HTML默认的复选框样式十分简陋,而以图片代替复选框的美化方式会给页面表单的处理带来麻烦,那 ...
- python 全栈开发,Day102(支付宝支付)
昨日内容回顾 1. django请求生命周期? - 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者po ...
- python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)
昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...
- python 全栈开发,Day63(子查询,MySQl创建用户和授权,可视化工具Navicat的使用,pymysql模块的使用)
昨日内容回顾 外键的变种三种关系: 多对一: 左表的多 对右表一 成立 左边的一 对右表多 不成立 foreign key(从表的id) refreences 主表的(id) 多对多 建立第三张表(f ...
- hihocoder 1343 : Stable Members【拓扑排序】
hihocoder #1343:题目 解释:一个学习小组,一共有N个学员,一个主管.每个学员都有自己的导师(一个或者多个),导师可以是其他学员也可以是主管.每周学员都要把自己的学习报告和收到的报告提交 ...
- Spark学习入门
Spark 是一种“One Stack to rule them all”通用的大数据计算框架,期望使用一个技术栈就完美地 解决大数据领域的各种计算任务. Spark特点:速度快.容易上手开发.超强的 ...
- vue中mixin的一点理解
vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情况下引入组件有什么区别? ...
- 023 SpringMVC拦截器
一:拦截器的HelloWorld 1.首先自定义拦截器 只要实现接口就行. package com.spring.it.interceptors; import javax.servlet.http. ...