@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自定义线程池处理异步任务的更多相关文章

  1. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  2. spring boot自定义线程池以及异步处理

    spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...

  3. SpringBoot 自定义线程池

    本教程目录: 自定义线程池 配置spring默认的线程池 1. 自定义线程池 1.1 修改application.properties task.pool.corePoolSize=20 task.p ...

  4. SpringBoot 自定义线程池,多线程

    原文:https://www.jianshu.com/p/832f2b162450 我们都知道spring只是为我们简单的处理线程池,每次用到线程总会new 一个新的线程,效率不高,所以我们需要自定义 ...

  5. SpringBoot—自定义线程池及并发定时任务模板

    介绍   在项目开发中,经常遇到定时任务,今天通过自定义多线程池总结一下SpringBoot默认实现的定时任务机制. 定时任务模板 pom依赖 <dependencies> <dep ...

  6. Spring Boot使用@Async实现异步调用:自定义线程池

    前面的章节中,我们介绍了使用@Async注解来实现异步调用,但是,对于这些异步执行的控制是我们保障自身应用健康的基本技能.本文我们就来学习一下,如果通过自定义线程池的方式来控制异步调用的并发. 定义线 ...

  7. 转载-SpringBoot结合线程池解决多线程问题实录;以及自己的总结

    原文地址:https://blog.csdn.net/GFJ0814/article/details/92422245 看看这篇文章(继续学习):https://www.jianshu.com/p/3 ...

  8. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  9. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

随机推荐

  1. OneNET麒麟座应用开发之五:获取加速度传感器ADXL345数据

    由于数据采集站基本都安装在野外或者楼顶,安装位置以及震动对检测数据的准确性有一定影响.所以想要有一个位置状态数据,正好发现麒麟作上有ADXL345,这样一个数字输出的加速度传感器.如图中红框所示: 1 ...

  2. OCM_第九天课程:Section4—》OCM课程环境搭建

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  3. JavaScript中的事件冒泡?事件传播的解释

    注:本文来源  可译网 事件冒泡是你在学习javaScript旅途中遇到的一个术语,它涉及到当一个元素被另一个元素嵌套时调用事件处理的顺序,并且两个元素注册了同一个事件(例如,点击事件). 但是事件冒 ...

  4. 总结Selenium WebDriver中一些鼠标和键盘事件的使用

    在使用 Selenium WebDriver 做自动化测试的时候,会经常模拟鼠标和键盘的一些行为.比如使用鼠标单击.双击.右击.拖拽等动作:或者键盘输入.快捷键使用.组合键使用等模拟键盘的操作.在 W ...

  5. Elasticsearch创建索引和映射结构详解

    前言 这篇文章详细介绍了如何创建索引和某个类型的映射. 下文中[address]指代elasticsearch服务器访问地址(http://localhost:9200). 1       创建索引 ...

  6. python 全栈开发,Day123(图灵机器人,web录音实现自动化交互问答)

    昨日内容回顾 . 百度ai开放平台 . AipSpeech技术,语言合成,语言识别 . Nlp技术,短文本相似度 . 实现一个简单的问答机器人 . 语言识别 ffmpeg (目前所有音乐,视频领域,这 ...

  7. webservice restful一个小例子

    需求 公司有一个产品,包括前台WEB界面和多个后台服务,各个服务都需要在前面界面中进行配置和控 制,以调整服务的行为.以前,配置文件都存放在数据库中,界面上修改配置后入库,并发送消息(Socket)通 ...

  8. Android各国语言对照表(values-xxx)

    eg: 阿拉伯 Arabic  SA values-ar Android各国语言对照表https://blog.csdn.net/jiangguohu1/article/details/5044014 ...

  9. ElasticSearch - How to search for a part of a word with ElasticSearch

    Search a part of word with ElasticSearch 来自stackoverflow https://stackoverflow.com/questions/6467067 ...

  10. day8--socket文件传输

    FTP server 1.读取文件名 2.检测文件是否存在 3.打开文件 4.检测文件大小(告诉客户端发送文件的大小) 5.发送文件大小和MD5值给客户端,MD5 6.等待客户端确认(防止粘包) 7. ...