除了之前介绍的创建线程方式外,spring boot为我们了提供一套完整的线程创建方式,其中包括了:线程、线程池、线程的监控。

一、使用spring boot提供的方法创建线程与线程池

  1.首先在spring boot 的启动类上加上注解:@EnableAsync

//开启异步线程必须加上注解
@EnableAsync
@SpringBootApplication
public class ThemApplication { public static void main(String[] args) {
SpringApplication.run(ThemApplication.class, args);
} }

 

 2.spring boot创建的线程,需要我们先创建线程池

/**
* 线程池的配置
*
* 需要加上这两个注解
*/
@Configuration
@EnableAsync
public class Pool implements AsyncConfigurer { @Bean("thread")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置线程名称
executor.setThreadNamePrefix("hello-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true); return executor;
} }

  

3.不带返回值的线程任务创建,线程任务创建很方便,只需要在线程方法使用@Async注解就行,并且把这个类交给spring来管理

@Configuration
public class UseTask { @Async
public void show(int i) {
System.out.println("线程" +i + " 执行异步任务:" ); }
}

  测试的结果:

  4.带返回值的线程任务创建

    带返回值的线程需要实现Future<T>方法,T表示返回的类型

@Configuration
public class UseTask { //带返回值的线程
@Async
public Future<Integer> showSum(int i,int j) {
int x=i+j;
System.out.println("当前执行的是第"+i+"线程");
return new AsyncResult<Integer>(x);
} }

  

可以看到这个方法返回的是一个Future<Integer>,所以我们要通过这个类中的get方法获取返回值

   @Test
public void thread() throws ExecutionException, InterruptedException {
int j = 0;
for (int i = 0; i < 10; i++) {
//返回的类型
Future<Integer> num = useTask.showSum(i, i);
//get方法获取返回值
j = num.get();
System.out.println("计算结果是" + j);
} }

二、spring boot线程池的监控

    springboot中监控线程的操作非常简便,只需要继承ThreadPoolTaskExecutor类就能实现

/**
* 监控线程的类很简单,只需要继承ThreadPoolTaskExecutor
*
*/
@Configuration
public class Monitor extends ThreadPoolTaskExecutor {
/**
* 创建一个线程安全的ConcurrentHashMap,存储监控的信息
*/
public ConcurrentHashMap<String, ThreadPoolTaskExecutor> threadPoolMap = new ConcurrentHashMap<>();
}

  

监控类创建好后,还需要在线程池配置中声明。修改后的pool类

/**
* 线程池的配置
*
* 需要加上这两个注解
*/
@Configuration
@EnableAsync
public class Pool implements AsyncConfigurer { @Autowired
Monitor monitor; @Bean("thread")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置线程名称
executor.setThreadNamePrefix("hello-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//配置线程池到线程监控类中,第一个参数为线程池的名称
monitor.threadPoolMap.put("thread", executor);
return executor;
} }

  

编写测试类,获取线程的监控数据

@RestController
public class Test { @Autowired
UseTask useTask; @Autowired
Monitor monitor; @RequestMapping(value="/test",method= RequestMethod.GET)
public void meetInitMain() throws InterruptedException {
    //线程任务的创建
useTask.show(1);
useTask.show(2);
useTask.show(3);
useTask.show(4);
useTask.show(5); //获取监控的信息,从threadPoolMap中得到在线程池配置类中put进去的线程池名称
ThreadPoolTaskExecutor monitorTask = monitor.threadPoolMap.get("thread");
     //threadPoolExecutor才是线程监控的信息存储类
ThreadPoolExecutor threadPoolExecutor= monitorTask.getThreadPoolExecutor();
//当前线程池中的工作线程数
int poolSize=threadPoolExecutor.getPoolSize();
//队列中的任务
int queueSize=threadPoolExecutor.getQueue().size();
//线程正在执行的任务
int activeCount=threadPoolExecutor.getActiveCount();
//已经执行完成的任务
Long completedTaskCount=threadPoolExecutor.getCompletedTaskCount();
//全部的任务数
Long taskCount=threadPoolExecutor.getTaskCount();
//线程池中曾经最大的线程数量
int largestPoolSize= threadPoolExecutor.getLargestPoolSize();
Thread.sleep(100);
System.out.println("当前线程池中的工作线程数:"+poolSize+" 队列中的任务有:"
+queueSize+" 正在执行的任务:"+activeCount
+" 已经执行完成的任务:"+completedTaskCount+" 全部的任务数:"+taskCount
+"线程池中曾经最大的线程数量:"+largestPoolSize); }
}

  连续请求两次测试地址,测试结果:

  

  

  

java并发学习--第二章 spring boot实现线程的创建的更多相关文章

  1. java并发学习--第九章 指令重排序

    一.happns-before happns-before是学习指令重排序前的一个必须了解的知识点,他的作用主要是就是用来判断代码的执行顺序. 1.定义 happens-before是用来指定两个操作 ...

  2. java并发学习--第一章 线程的创建

    所谓的并发就是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行.所以我们看似几个线程在同时进行,其实在操作系统中 ...

  3. Java并发学习之二——获取和设置线程信息

    本文是学习网络上的文章时的总结,感谢大家无私的分享. Thread类的对象中保存了一些属性信息可以帮助我们辨别每个线程.知道它的一些信息 ID:每一个线程的独特标示: Name:线程的名称: Prio ...

  4. java并发学习--第八章 JDK 8 中线程优化的新特性

    一.新增原子类LongAdder LongAdder是JDK8中AtomicLong的增强工具类,它与AtomicLong最大的不同就是:在多线程场景下,LongAdder中对单一的变量进行拆分成多个 ...

  5. Spring学习指南-第二章-Spring框架基础(完)

    第二章 Spring框架基础 面向接口编程的设计方法 ​ 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...

  6. Java精选面试题之Spring Boot 三十三问

    Spring Boot Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一: Spring Boot.Spring MVC 和 ...

  7. 第5章 Spring Boot 功能

    Spring Boot 功能 本节将会介绍Spring Boot的一些细节. 在这里,您可以了解您将要使用和自定义的主要功能. 如果还没有准备好,您可能需要阅读第二部分“入门指南”和第三部分“使用 S ...

  8. 【Todo】Java并发学习 & 示例练习及代码

    接上一篇:http://www.cnblogs.com/charlesblc/p/6097111.html <Java并发学习 & Executor学习 & 异常逃逸 & ...

  9. 第3章 Spring Boot 入门指南

    Part II. 入门指南 如果你刚刚开始使用Spring Boot,这是你的一部分内容! 在这里我们将会回答一些基本的“what?”, “how?” 和 “why?”的问题. 在这里你会找到一个详细 ...

随机推荐

  1. view组件

    view标签的属性值: hover-class:按下的点击态       属性值:字符串 如果:hover-class="none" 按下就没有点击态 hover-stop-pro ...

  2. node.js运行配置(vs code非控制台输出)

    node.js运行配置(vs code非控制台输出) node  配置 简化  vs code 是非常强大的编译器,皆因它有有各种各样好用的插件. 在没有安装code runner插件之前,想要执行n ...

  3. leetcode-mid-array-5. Longest Palindromic Substring

    mycode   12.51% class Solution(object): def longestPalindrome(self, s): """ :type s: ...

  4. 【洛谷P1219 八皇后】

    参考思路见白书(一本通) 题目链接 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上 ...

  5. mycat 配置简介

    最近在看 mycat ,官网: http://www.mycat.io/  上面就有 PDF 的教程下载.但是对于我这个初学者来讲,搭建环境的时候还是有点晕,下面从一个简单的例子来讲解相关配置.我用的 ...

  6. original和source的区别

    最近跟网页翻译怼上了,在给翻译前的页面起名是纠结于使用original page还是source page,就查了一下original和source的区别. original: n. 原件:原作:原物 ...

  7. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_02 递归_3_练习_使用递归计算阶乘

    结束条件是乘到 当前数字等于1

  8. 操作excel--xlwt/xlrd/xlutils模块

    一.写Excel (导入xlwt模块)需求:只要你传入一个表名,就能把所有的数据导入出来写入excel,字段名是excel的表头分析: 1.要动态获取到表的字段 cur.description能获取到 ...

  9. R语言平均值,中位数和众数

    R语言平均值,中位数和众数 R中的统计分析通过使用许多内置函数来执行的.这些函数大部分是R基础包的一部分.这些函数将R向量与参数一起作为输入,并在执行计算后给出结果. 我们在本章中讨论的是如何求平均值 ...

  10. 搭建 Git 服务器(基于 CentOS 7)

    服务器上的-Git-架设服务器-官网参考 对于规模比较小的团队,可以直接搭建 Git 服务器,逐个收集研发同学的证书配置进来即可.如果团队规模比较大,可以直接采用 GitLab.Drone 等现成的带 ...