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中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...
随机推荐
- 论文笔记系列-Simple And Efficient Architecture Search For Neural Networks
摘要 本文提出了一种新方法,可以基于简单的爬山过程自动搜索性能良好的CNN架构,该算法运算符应用网络态射,然后通过余弦退火进行短期优化运行. 令人惊讶的是,这种简单的方法产生了有竞争力的结果,尽管只需 ...
- Android Retrofit 2.0使用
实例带你了解Retrofit 2.0的使用,分享目前开发Retrofit遇到的坑和心得. 添加依赖 app/build.gradle 1 compile 'com.squareup.retrofit2 ...
- SILC超像素分割算法详解(附Python代码)
SILC算法详解 一.原理介绍 SLIC算法是simple linear iterative cluster的简称,该算法用来生成超像素(superpixel) 算法步骤: 已知一副图像大小M*N,可 ...
- Java泛型方法与泛型类的使用------------(五)
泛型的本质就是将数据类型也参数化, 普通方法的输入参数的值是可以变的,但是类型(比如: String)是不能变的,它使得了在面对不同类型的输入参数的时候我们要重载方法才行. 泛型就是将这个数据类型也搞 ...
- 基于theano的降噪自动编码器(Denoising Autoencoders--DA)
1.自动编码器 自动编码器首先通过下面的映射,把输入 $x\in[0,1]^{d}$映射到一个隐层 $y\in[0,1]^{d^{'}}$(编码器): $y=s(Wx+b)$ 其中 $s$ 是非线性的 ...
- 【vim】跳转到上/下一个修改的位置
当你编辑一个很大的文件时,经常要做的事是在某处进行修改,然后跳到另外一处.如果你想跳回之前修改的地方,使用命令: Ctrl+o 来回到之前修改的地方 类似的: Ctrl+i 会回退上面的跳动.
- Linux Makefile 编译速度的优化【转】
转自:https://blog.csdn.net/QQ1452008/article/details/51851801 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...
- Android网络通信(8):WiFi Direct
Android网络通信之WiFi Direct 使用Wi-Fi Direct技术可以让具备硬件支持的设备在没有中间接入点的情况下进行直接互联.Android 4.0(API版本14)及以后的系统都提供 ...
- 深入浅出 JavaScript 关键词 -- this
深入浅出 JavaScript 关键词 -- this 要说 JavaScript 这门语言最容易让人困惑的知识点,this 关键词肯定算一个.JavaScript 语言面世多年,一直在进化完善,现在 ...
- mockito简单教程
注:本文来源:sdyy321的<mockito简单教程> 官网: http://mockito.org API文档:http://docs.mockito.googlecode.com/h ...