Java定时线程池停止超时任务
一、背景
题主最近遇到一个问题,本来通过ScheduledExecutorService线程池定时调度一个任务。奈何不知道为啥跑了2个多月,其中一个任务Hang住了,原本定时的任务则出现了问题。
关于定时线程池,好多人认为设置好频率(比如1Min),它会按照这个间隔按部就班的工作。但是,如果其中一次调度任务卡住的话,不仅这次调度失败,而且整个线程池也会停在这次调度上。
我们先从一个例子试着复现下问题:
public class pool {
private static class Runner implements Runnable {
@Override
public void run() {
try {
Thread.sleep(10000);
System.out.println(new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ScheduledExecutorService service
= Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(
new Runner(), 0, 1, TimeUnit.SECONDS);
}
}
先从Main看,启动一个定时线程池,每隔1S调度一次Runner。看上去,应该是1S调度一次,但是Runner的实际执行时间为10S,那多久会调度一次?答案是10S。
所以说,这个Runner不管什么原因挂掉了或者Hang住了,那这个定时调度线程池基本就废了。
二、解决方法
那我们应该怎么解决这个问题?如果说定时线程池有任务调度的超时策略就完美了,很可惜并没有。
我们想下在并发编程中,哪种方式有超时策略?
对,Future有,那我们可以结合Future,提供一种自动停止超时任务的方式,来解决某个任务Hang住的问题。
我们简单修改下,把sleep逻辑移动到Callable中,并在Runner中使用Future来控制超时。
public class pool {
private static class Caller implements Callable<Boolean> {
@Override
public Boolean call() {
try {
Thread.sleep(10000);
System.out.println(new Date());
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
private static class Runner implements Runnable {
@Override
public void run() {
ExecutorService excutor = Executors.newSingleThreadExecutor();
Future<Boolean> future = excutor.submit(new Caller());
try {
future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
System.out.println("timeout");
} catch (Exception e) {
e.printStackTrace();
} finally {
excutor.shutdownNow(); // 强制终止任务
}
}
}
public static void main(String[] args) {
ScheduledExecutorService service
= Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(
new Runner(), 0, 1, TimeUnit.SECONDS);
}
}
备注:
- 实现逻辑相当于转移了,把本来应该调度的任务交给了另外一个Future单线程去执行。因为存在超时逻辑,不会影响原有定时线程池的执行。
- finally是否需要杀死线程池,因人而异。如果不杀死的话,那超时的任务会继续执行。
题外话:如果你有好的解决方式,欢迎和题主探讨。谢谢。
Java定时线程池停止超时任务的更多相关文章
- ScheduledThreadPoolExecutor源码分析-你知道定时线程池是如何实现延迟执行和周期执行的吗?
Java版本:8u261. 1 简介 ScheduledThreadPoolExecutor即定时线程池,是用来执行延迟任务或周期性任务的.相比于Timer的单线程,定时线程池在遇到任务抛出异常的时候 ...
- Java并发——线程池Executor框架
线程池 无限制的创建线程 若采用"为每个任务分配一个线程"的方式会存在一些缺陷,尤其是当需要创建大量线程时: 线程生命周期的开销非常高 资源消耗 稳定性 引入线程池 任务是一组逻辑 ...
- Java中线程池的学习
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程 ...
- 【java】-- 线程池原理分析
1.为什么要学习使用多线程? 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担. 线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致 ...
- Java中线程池的实现原理
知识点总结 ---------------------------------------------------------------------------------------------- ...
- Java中线程池的实现原理-求职必备
jdk1.5引入Executor线程池框架,通过它把任务的提交和执行进行解耦,只需要定义好任务,然后提交给线程池,而不用关心该任务是如何执行.被哪个线程执行,以及什么时候执行. 初始化线程池(4种) ...
- 深入理解Java之线程池(爱奇艺面试)
爱奇艺的面试官问 (1) 线程池是如何关闭的 (2) 如何确定线程池的数量 一.线程池销毁,停止线程池 ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown() ...
- Java中线程池,你真的会用吗?
在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...
- 沉淀再出发:java中线程池解析
沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...
随机推荐
- Activity生命周期函数、onSaveInstanceState()和onRestoreInstanceState()的介绍
http://www.cnblogs.com/tianzhijiexian/p/3885472.html
- transform 图标旋转,IE8、IE7不兼容
要将图标旋转,只需使用transform的rotate以及transition即可完成旋转的动画效果.ease 规定慢速开始,然后变快,然后慢速结束的过渡效果; ease-in 规定以慢速开始的过 ...
- android 使用SQLite存储数据
创建一个类继承SQLiteOpenHelper,重写他的构造方法.onCreate().onUpgrade() 构建出SQLiteOpenHelper实例后,再调用他的getReadableDatab ...
- 【转】Python基础语法
[转]Python基础语法 学习一门编程语言,通常是学习该语言的以下几个部分的内容: 基础语法:如,变量的声明与调用.基本输出语句.代码块语法.注释等: 数据类型:通常都为 数字.字符串.布尔值.数组 ...
- mono修改配置
当前mono安装目录为:/home/mono,安装成功后修改配置需进入这个路径: cd /home/mono 1.修改TcpBinaryFrameManager.cs文件 cd /home/mono/ ...
- oracle查看表名称和表字段注释
--查询该表字段的注释select * from user_col_comments where Table_Name like '%SMS%' --查询类似表select * from user_t ...
- 内核中 subsys_initcall 以及初始化标号
今天在看内核中无线的实现时,发现一个调用 subsys_initcall(cfg80211_init);搜索一些资料: subsys_initcall 的定义在 include/linux/init. ...
- 配置mysql5.5主从复制、半同步复制、主主复制
mysql主服务器 192.168.8.40 mysql从服务器 192.168.8.41 全新配置过程(主和从数据库都没有数据): 主从复制主服务器设置: 1.改server-id 2.启 ...
- eslint ":"号
eslint规则默认是没有;号的,如果也没要加;号,那就要在.eslintrc.js里面,加配置: 'semi':['error',always'] 强制有;号,没有就报错 参考地址:http:/ ...
- python接口自动化测试一:http协议
1. http简介:http(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议 2. url详解:百度搜索的一个url地址:https://www.baidu.com/s?wd=%E ...