介绍

  在项目开发中,经常遇到定时任务,今天通过自定义多线程池总结一下SpringBoot默认实现的定时任务机制。

定时任务模板

pom依赖

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
//线程池用到
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
//@Slf4j注解用到
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.4</version>
</dependency>
</dependencies>

自定义线程池模板

package com.example.andya.demo.conf;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.concurrent.*; /**
* @author Andya
* @create 2020-05-29 14:08
*/
@Configuration
public class ThreadPoolConfig { public static String THREAD_NAME = "first-thread-pool-%d";
public static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2 + 1;
public static int MAX_POOL_SIZE = 10;
public static int QUEUE_SIZE = 10; /**
* 自定义消费队列线程池
*
* @return
*/
@Bean(value = "firstThreadPool")
public ExecutorService buildFirstThreadPool() {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(THREAD_NAME).build(); /**
* 1. CallerRunsPolicy : 这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。
2. AbortPolicy : 对拒绝任务抛弃处理,并且抛出异常。
3. DiscardPolicy : 对拒绝任务直接无声抛弃,没有异常信息。
4. DiscardOldestPolicy : 对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。
*/
ExecutorService threadPool = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
0L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(QUEUE_SIZE),
threadFactory,
new ThreadPoolExecutor.AbortPolicy());
return threadPool;
}
}

定时任务模板

package com.example.andya.demo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; /**
* @author Andya
* @create 2020-05-29 14:26
*/
@Service
@EnableScheduling
@Slf4j
public class TestThreadPool {
@Resource(name = "firstThreadPool")
private ExecutorService firstThreadPool; @Scheduled(cron = "0 * * * * *")
public void test1SchedulerThreadPool() {
final CountDownLatch countDownLatch = new CountDownLatch(5);
log.info("Begin schedule-【1】 startTime: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
for (int i = 0; i < 5; i++) {
firstThreadPool.execute(() -> {
countDownLatch.countDown();
log.info("schedule-【1】 , threadPool info: {}, countDownLatch info: {}", firstThreadPool.toString(), countDownLatch.toString());
});
}
try {
countDownLatch.await(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
log.error("schedule-【1】timeout, {}", e.getMessage());
} finally {
log.info("schedule-【1】 multi-threading countDownLatch count: {}", countDownLatch.getCount());
}
log.info("End schedule-【1】 startTime: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} @Scheduled(cron = "0 * * * * *")
public void test2SchedulerThreadPool() {
final CountDownLatch countDownLatch = new CountDownLatch(5);
log.info("Begin schedule-【2】 startTime: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
for (int i = 0; i < 5; i++) {
firstThreadPool.execute(() -> {
countDownLatch.countDown();
log.info("schedule-【2】, threadPool info {}, countDownLatch info: {}", firstThreadPool.toString(), countDownLatch.toString());
});
}
try {
countDownLatch.await(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
log.error("schedule-【2】timeout, {}", e.getMessage());
} finally {
log.info("schedule-【2】 multi-threading countDownLatch count: {}", countDownLatch.getCount());
}
log.info("End schedule-【2】 startTime: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}

运行结果

2020-05-29 15:45:00.011  INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool    : Begin schedule-【2】 startTime: 2020-05-29 15:45:00
2020-05-29 15:45:00.018 INFO 6900 --- [t-thread-pool-0] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 0], countDownLatch info: java.util.concurrent.CountDownLatch@522af59c[Count = 4]
2020-05-29 15:45:00.019 INFO 6900 --- [t-thread-pool-1] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 5, active threads = 4, queued tasks = 0, completed tasks = 1], countDownLatch info: java.util.concurrent.CountDownLatch@522af59c[Count = 3]
2020-05-29 15:45:00.019 INFO 6900 --- [t-thread-pool-2] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 5, active threads = 3, queued tasks = 0, completed tasks = 2], countDownLatch info: java.util.concurrent.CountDownLatch@522af59c[Count = 2]
2020-05-29 15:45:00.019 INFO 6900 --- [t-thread-pool-3] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 5, active threads = 2, queued tasks = 0, completed tasks = 3], countDownLatch info: java.util.concurrent.CountDownLatch@522af59c[Count = 1]
2020-05-29 15:45:00.019 INFO 6900 --- [t-thread-pool-4] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 5, active threads = 1, queued tasks = 0, completed tasks = 4], countDownLatch info: java.util.concurrent.CountDownLatch@522af59c[Count = 0]
2020-05-29 15:45:00.019 INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : schedule-【2】 multi-threading countDownLatch count: 0
2020-05-29 15:45:00.019 INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : End schedule-【2】 startTime: 2020-05-29 15:45:00
2020-05-29 15:45:00.020 INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : Begin schedule-【1】 startTime: 2020-05-29 15:45:00
2020-05-29 15:45:00.021 INFO 6900 --- [t-thread-pool-0] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 9, active threads = 5, queued tasks = 0, completed tasks = 5], countDownLatch info: java.util.concurrent.CountDownLatch@5ced01a9[Count = 4]
2020-05-29 15:45:00.023 INFO 6900 --- [t-thread-pool-5] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 9, active threads = 4, queued tasks = 0, completed tasks = 6], countDownLatch info: java.util.concurrent.CountDownLatch@5ced01a9[Count = 3]
2020-05-29 15:45:00.024 INFO 6900 --- [t-thread-pool-6] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 9, active threads = 3, queued tasks = 0, completed tasks = 7], countDownLatch info: java.util.concurrent.CountDownLatch@5ced01a9[Count = 2]
2020-05-29 15:45:00.024 INFO 6900 --- [t-thread-pool-7] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 9, active threads = 3, queued tasks = 0, completed tasks = 7], countDownLatch info: java.util.concurrent.CountDownLatch@5ced01a9[Count = 1]
2020-05-29 15:45:00.025 INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : schedule-【1】 multi-threading countDownLatch count: 0
2020-05-29 15:45:00.025 INFO 6900 --- [t-thread-pool-8] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@26b894bd[Running, pool size = 9, active threads = 3, queued tasks = 0, completed tasks = 7], countDownLatch info: java.util.concurrent.CountDownLatch@5ced01a9[Count = 0]
2020-05-29 15:45:00.025 INFO 6900 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : End schedule-【1】 startTime: 2020-05-29 15:45:00

从上述结果中可以看出,虽然是test1SchedulerThreadPool()test2SchedulerThreadPool()都是每分钟执行定时任务,但是明显两个方法没有并发执行,而是串行执行的。

并发定时器模板

通过增加一个配置类来并发执行定时任务。

package com.example.andya.demo.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar; import java.util.concurrent.Executors; /**
* @author Andya
* @create 2020-05-29 15:52
*/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}

运行结果

2020-05-29 15:53:00.005  INFO 3028 --- [pool-2-thread-2] c.e.andya.demo.service.TestThreadPool    : Begin schedule-【2】 startTime: 2020-05-29 15:53:00
2020-05-29 15:53:00.015 INFO 3028 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : Begin schedule-【1】 startTime: 2020-05-29 15:53:00
2020-05-29 15:53:00.019 INFO 3028 --- [t-thread-pool-0] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 9, queued tasks = 1, completed tasks = 0], countDownLatch info: java.util.concurrent.CountDownLatch@630f649f[Count = 3]
2020-05-29 15:53:00.020 INFO 3028 --- [t-thread-pool-3] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 9, queued tasks = 1, completed tasks = 0], countDownLatch info: java.util.concurrent.CountDownLatch@630f649f[Count = 1]
2020-05-29 15:53:00.019 INFO 3028 --- [t-thread-pool-1] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 9, queued tasks = 1, completed tasks = 0], countDownLatch info: java.util.concurrent.CountDownLatch@630f649f[Count = 3]
2020-05-29 15:53:00.019 INFO 3028 --- [t-thread-pool-2] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 9, queued tasks = 1, completed tasks = 0], countDownLatch info: java.util.concurrent.CountDownLatch@630f649f[Count = 2]
2020-05-29 15:53:00.021 INFO 3028 --- [t-thread-pool-0] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 6, queued tasks = 0, completed tasks = 4], countDownLatch info: java.util.concurrent.CountDownLatch@5ebb120e[Count = 4]
2020-05-29 15:53:00.021 INFO 3028 --- [t-thread-pool-4] c.e.andya.demo.service.TestThreadPool : schedule-【2】, threadPool info java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 5, queued tasks = 0, completed tasks = 5], countDownLatch info: java.util.concurrent.CountDownLatch@630f649f[Count = 0]
2020-05-29 15:53:00.021 INFO 3028 --- [pool-2-thread-2] c.e.andya.demo.service.TestThreadPool : schedule-【2】 multi-threading countDownLatch count: 0
2020-05-29 15:53:00.022 INFO 3028 --- [pool-2-thread-2] c.e.andya.demo.service.TestThreadPool : End schedule-【2】 startTime: 2020-05-29 15:53:00
2020-05-29 15:53:00.022 INFO 3028 --- [t-thread-pool-5] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 4, queued tasks = 0, completed tasks = 6], countDownLatch info: java.util.concurrent.CountDownLatch@5ebb120e[Count = 3]
2020-05-29 15:53:00.022 INFO 3028 --- [t-thread-pool-6] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 3, queued tasks = 0, completed tasks = 7], countDownLatch info: java.util.concurrent.CountDownLatch@5ebb120e[Count = 2]
2020-05-29 15:53:00.024 INFO 3028 --- [t-thread-pool-7] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 2, queued tasks = 0, completed tasks = 8], countDownLatch info: java.util.concurrent.CountDownLatch@5ebb120e[Count = 1]
2020-05-29 15:53:00.024 INFO 3028 --- [t-thread-pool-8] c.e.andya.demo.service.TestThreadPool : schedule-【1】 , threadPool info: java.util.concurrent.ThreadPoolExecutor@5149f008[Running, pool size = 9, active threads = 2, queued tasks = 0, completed tasks = 8], countDownLatch info: java.util.concurrent.CountDownLatch@5ebb120e[Count = 0]
2020-05-29 15:53:00.024 INFO 3028 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : schedule-【1】 multi-threading countDownLatch count: 0
2020-05-29 15:53:00.024 INFO 3028 --- [pool-2-thread-1] c.e.andya.demo.service.TestThreadPool : End schedule-【1】 startTime: 2020-05-29 15:53:00

可以从运行结果中看到,test1SchedulerThreadPool()test2SchedulerThreadPool()两个方法同时打印了Begin schedule...信息,是并发定时。

SpringBoot—自定义线程池及并发定时任务模板的更多相关文章

  1. SpringBoot自定义线程池处理异步任务

    @Async异步调用 就不解释什么是异步调用了,Spring Boot中进行异步调用很简单 1.通过使用@Async注解就能简单的将原来的同步函数变为异步函数 package com.winner.s ...

  2. SpringBoot 自定义线程池

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

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

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

  4. JAVA并发,线程工厂及自定义线程池

    package com.xt.thinks21_2; import java.util.concurrent.ExecutorService; import java.util.concurrent. ...

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

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

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

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

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

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

  8. Android 自定义线程池的实战

    前言:在上一篇文章中我们讲到了AsyncTask的基本使用.AsyncTask的封装.AsyncTask 的串行/并行线程队列.自定义线程池.线程池的快速创建方式. 对线程池不了解的同学可以先看 An ...

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

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

随机推荐

  1. P2620 虫洞

    题目背景 applepi 想进行宇宙旅行.当然,applepi 知道这是有可能的,因为applepi 的特殊能力能使他观测到宇宙中的虫洞.所谓虫洞就是一个在三维之外的维度打开的快捷通道,通过虫洞能够从 ...

  2. RF(作用与目的)

    1.robotframework 自动化原理 通过 ride 工具编写脚本,加载指定的 UI 测试库,再通过 pybot 程序去运行指定脚本,调用浏览器驱动,打开浏览器,操作浏览器页面元素,达到模拟用 ...

  3. 微软2016校园招聘在线笔试之Magic Box

    题目1 : Magic Box 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 The circus clown Sunny has a magic box. When ...

  4. jQuery的事件绑定与触发 - 学习笔记

    jQuery的事件绑定与触发 事件绑定 自动触发事件 常用的鼠标事件 事件冒泡和默认行为 事件冒泡 默认行为 获得当前鼠标的位置和按键 jQuery的事件绑定与触发 事件绑定 基本绑定 $(eleme ...

  5. 【Spark】使用java语言开发spark程序

    目录 步骤 一.创建maven工程,导入jar包 二.开发代码 步骤 一.创建maven工程,导入jar包 <properties> <scala.version>2.11.8 ...

  6. 【Hadoop离线基础总结】oozie定时任务设置

    目录 简介 概述 oozie定时任务设置 1.拷贝定时任务的调度模板 拷贝hello.sh脚本 3.修改配置文件 4.上传到hdfs对应路径 5.运行定时任务 简介 概述 在oozie当中,主要是通过 ...

  7. 【Hadoop离线基础总结】oozie调度hive

    目录 1.拷贝hive的案例模板 2.编辑hive模板 3.上传工作文件到hdfs 4.执行oozie的调度 5.查看调度结果 1.拷贝hive的案例模板 cd /export/servers/ooz ...

  8. 中文分词工具简介与安装教程(jieba、nlpir、hanlp、pkuseg、foolnltk、snownlp、thulac)

    2.1 jieba 2.1.1 jieba简介 Jieba中文含义结巴,jieba库是目前做的最好的python分词组件.首先它的安装十分便捷,只需要使用pip安装:其次,它不需要另外下载其它的数据包 ...

  9. [csu/coj 1619] 递归

    题意:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1619 思路:由于式子具有递归的性质,考虑递归解,中间结果会超64位int,需用大数.另外自己 ...

  10. 正则表达式 [:graph:] 含义

    [:graph:] 代表printable and visible的字符,是除空格符(空格键与[TAB]键)之外的所有按键, 控制字符不算[:graph:] https://www.regular-e ...