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的基本用法,到简单的封装,再到 ...
随机推荐
- LeetCode(58): 最后一个单词的长度
Easy! 题目描述: 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 说明:一个单词是指由字母组成,但不包含任何空格的字符串. ...
- python 全栈开发,Day77(图书管理系统)
一.图书管理系统 完整代码链接: https://github.com/py3study/bms_multi 本项目使用session来实现一个简单的图书管理系统 未登录不允许访问后台: 直接访问后台 ...
- Thread类中的join方法
package charpter06; //类实现接口public class Processor implements Runnable { // 重写接口方法 @Override public v ...
- #5【BZOJ4275】[ONTAK2015]Badania
Description 给定三个数字串A,B,C,请找到一个A,B的最长公共子序列,满足C是该子序列的子串. Input 第一行包含一个正整数n(1<=n<=3000),表示A串的长度. ...
- Matrix Power Series POJ3233
递推思想 先放着 见 https://www.cnblogs.com/jackge/p/3147604.html
- mac OS X下Java项目环境搭建+IntelliJ IDEA Jrebel插件安装与破解+Office 2016破解版安装
一.mac OS X下Java项目环境搭建 因为某些原因新入手了台最新版的MacBook Pro,意味着今天要花一天时间安装各种软件以及项目环境搭建╮(╯▽╰)╭ 项目环境搭建步骤: 1.安装jdk ...
- @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
详细错误信息 Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Re ...
- js数据结构之二叉树的详细实现方法
数据结构中,二叉树的使用频率非常高,这得益于二叉树优秀的性能. 二叉树是非线性的数据结构,用以存储带有层级的数据,其用于查找的删除的性能非常高. 二叉树 数据结构的实现方法如下: function N ...
- [软件研究]对wdcp v3的一次小研究#1
0x00 前言 好久没有更新了,已经长草无疑. 之前团队要搞个测验的系统,用来安全培训考核,团队内又没啥人搞开发的,自己又想学一下vue,就用vue+ci 撸了一个. 搞了一个星期基本搞完(开发能力真 ...
- L1 与 L2 正则化
参考这篇文章: https://baijiahao.baidu.com/s?id=1621054167310242353&wfr=spider&for=pc https://blog. ...