JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理
本文记录:
1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败。
2,使用普通的Thread类来执行任务,在main线程中周期性创建线程,提交任务。然后,使用UncaughtExceptionHandler来处理异常。
一,正常任务执行
负责执行任务的线程类如下:(一个计算阶乘的任务,计算5以上的阶乘,就会抛出异常)
public class FactorialCalc implements Runnable {
private Integer number;
public FactorialCalc(Integer number) {
this.number = number;
}
public void run() {
int result = 1;
if (number == 0) {
System.out.println("0!=" + "1");
}
if (number > 5) {
System.out.println("exception");
throw new IllegalArgumentException(">5");
}
for(int i = 1; i <= number; i++) {
result *= i;
}
System.out.println(number + "!=" + result);
}
}
测试的Main类如下:
public class MainPeriod {
public static void main(String[] args) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
FactorialCalc task1 = new FactorialCalc(6);
FactorialCalc task2 = new FactorialCalc(3);
ScheduledFuture<?> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);
// ScheduledFuture<?> result = executorService.scheduleAtFixedRate(task2, 0, 2, TimeUnit.SECONDS);
try {
TimeUnit.SECONDS.sleep(5);
executorService.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ScheduledFuture<?> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);
提交一个Runnable任务,延迟为0,每1秒钟执行一次。
二,线程 执行过程中出现异常
当提交 task1 时,线程在执行过程中会抛出异常。
FactorialCalc task1 = new FactorialCalc(6);//计算6的阶乘,6大于5
ScheduledFuture<?> result = executorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);
此时,如果注释掉 //executorService.shutdown(); 则线程池不会中止,因为这是一个线程池,所有的异常都由线程池catch住了。但是由于线程执行过程中抛出了异常,任务也不会周期性地执行了。参考JDK里面的scheduleAtFixedRate注释:
* If any execution of the task
* encounters an exception, subsequent executions are suppressed. public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);

三,关闭线程池 ,执行 executorService.shutdown() 语句
若线程池线程 执行任务过程中抛出了异常,但是在 主线程中 执行了executorService.shutdown() 语句,则会正常关闭 线程池。
四,总结
使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务时,如果任务一直正常执行,则任务会按设定的执行周期一直在运行(前提是,主线程内不要调用executorService.shutdown() ,比如需要 执行 永久性的周期性任务,那就不能调用 executorService.shutdown() )。
如果任务在某次执行过程中抛出了异常,则周期性任务会被中断,后续也不会再生成任务了,如果主线程 也没有 调用 executorService.shutdown() ,那线程池就不会关闭了。
五,使用Thread类执行任务,在Main线程中通过while循环周期性提交任务,使用UncaughtExceptionHandler来处理异常
import java.util.Random;
import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) { Random rand = new Random(); while(true){
int number = rand.nextInt(10);
Thread t = new Thread(new FactorialCalc(number));
t.setUncaughtExceptionHandler(new ExceptionHandler());
t.start();
try{
System.out.println("sleep 4s for next task");
TimeUnit.SECONDS.sleep(4);
}catch(InterruptedException e){ }
}
}
}
在main方法中使用一个while(true)循环,周期性地创建线程 提交任务。
第12-13行,每创建一个线程,调用setUncaughtExceptionHandler方法设置异常处理。关于异常处理,可参考:JAVA线程未捕获异常处理
第15-18行,线程每隔4s提交一次任务,从而实现任务的周期性执行。
异常处理类ExceptionHandler类实现了UncaughtExceptionHandler接口,然后在uncaughtException方法里面定义具体的异常处理过程即可。
import java.lang.Thread.UncaughtExceptionHandler;
public class ExceptionHandler implements UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("illegal exception: 计算的阶乘大于5了," + e.getMessage());
}
}
与线程池方式相比 ,这种方式是每个周期,都要new一个线程。而线程池则是每个周期new一个任务,把任务提交给线程池即可。
原文:http://www.cnblogs.com/hapjin/p/7616068.html
JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理的更多相关文章
- 让Java线程池实现任务阻塞执行的一种可行方案
Java的线程池一般是基于concurrent包下的ThreadPoolExecutor类实现的, 不过当我们基于spring框架开发程序时, 通常会使用其包装类ThreadPoolTaskExecu ...
- java 线程池 ScheduledExecutorService
ScheduledExecutorService执行周期性或定时任务 https://blog.csdn.net/u013851082/article/details/70207640
- Java线程池实现原理及其在美团业务中的实践
本文转载自Java线程池实现原理及其在美团业务中的实践 导语 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供 ...
- 解决Java线程池任务执行完毕后线程回收问题
转载请注明出处:http://www.cnblogs.com/pengineer/p/5011965.html 对于经常使用第三方框架进行web开发的程序员来说,Java线程池理所 ...
- 捕获Java线程池执行任务抛出的异常
捕获Java线程池执行任务抛出的异常Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常, public interface Runnable { publi ...
- java 线程池 并行 执行
https://github.com/donaldlee2008/JerryMultiThread/blob/master/src/com/jerry/threadpool/ThreadPoolTes ...
- Java如何判断线程池所有任务是否执行完毕
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Tes ...
- 由浅入深理解Java线程池及线程池的如何使用
前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...
- 【java线程池】
一.概述 1.线程池的优点 ①降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗: ②提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行: ③方便线程并发数的管控,线 ...
随机推荐
- 【BZOJ5332】[SDOI2018]旧试题(数论,三元环计数)
[BZOJ5332][SDOI2018]旧试题(数论,三元环计数) 题面 BZOJ 洛谷 题解 如果只有一个\(\sum\),那么我们可以枚举每个答案的出现次数. 首先约数个数这个东西很不爽,就搞一搞 ...
- Dynamic CRM 2015学习笔记(1)Azure 上安装 CRM 2015
今天终于在Azure上安装成功了CRM 2015,下面简单介绍下安装过程,以及出现问题的解决: 一. 配置AD, 安装IIS 参考下面的link,里面有详细的配置步骤 http://www.c-sha ...
- LOJ#6285. 数列分块入门 9
有点难..... 要求区间众数,所以我可以先把区间分块,然后我预处理出从第 i 块到第 j 块的众数,用dp[i][j]记录下来. 因为需要知道众数的num值, 所以我可以用一个vector来保存每个 ...
- CANOE入门(二)
CAPL就是Communication Application Programming Laguage的缩写,CAPL类似于C语言的语法,因此所有的语法请参考C语言教程,这里不在这里进行详述,关于C语 ...
- nginx+腾讯云免费ssl证书+阿里云ECS实现Https配置
1. 申请SSL证书: 首先我们需要到腾讯云那边申请一个ssl证书,对于个人博客类型的,建议采用免费版本,土豪除外 申请地址:https://console.cloud.tencent.com/ssl ...
- QQ邮箱无限扩容 + XMind8 Update8 Crack 小记
QQ邮箱扩容 三个月后还可以扩容 XMind8 Update8 Crack 软件地址 软件下载地址:https://www.xmind.cn/download/xmind8 补丁地址 破解补丁下载地址 ...
- Spring注解方式实现任务调度
原文:http://docs.spring.io/spring/docs/4.0.1.BUILD-SNAPSHOT/javadoc-api/ 注解类型:EnableScheduling @Target ...
- GNOME 3.28 启用桌面图标
原由 GNOME 3.28合并了移除桌面图标支持 Nautilus从此不在支持桌面图标,直到找到新的解决方案 Issues地址:https://gitlab.gnome.org/GNOME/nauti ...
- 【洛谷P2585】三色二叉树
题目大意:给定一个二叉树,可以染红绿黄三种颜色,要求父节点和子节点的颜色不同,且如果一个节点有两个子节点,那么两个子节点之间的颜色也不同.求最多和最少有多少个节点会被染成绿色. 题解:加深了对二叉树的 ...
- bzoj3829 POI2014 FAR-FarmCraft
题目链接 思路 用\(f[i]\)表示完成第\(i\)棵子树所需要得时间. 考虑如果有两个子树\(a\)和\(b\),如果先去完成子树\(a\),那么对于花费得时间就是\(f[b] + siz[a] ...