<线程池-定时任务> ScheduledExecutorService之shutdown引发的RejectedExecutionException问题
一、 问题描述
先来看一下异常信息,启动tomcat时就报错:
- 2015-3-20 15:22:39 org.apache.catalina.core.StandardContext listenerStart
- 严重: Exception sending context initialized event to listener instance of class
- com.***.***.action.GateWayMonitorListener
- java.util.concurrent.RejectedExecutionException
- at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution
- (ThreadPoolExecutor.java:1774)
- at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.jav
- a:768)
- at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(Sched
- uledThreadPoolExecutor.java:215)
- at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleWithFixedDel
- ay(ScheduledThreadPoolExecutor.java:443)
- at com.***.***.action.GateWayMonitorListener
- .scheduleEmailAndSms(GateWayMonitorListener.java:77)
- at com.***.***.action.GateWayMonitorListener
- .contextInitialized(GateWayMonitorListener.java:67)
- at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
- t.java:4206)
- at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
- 705)
- at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase
- .java:799)
- at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:77
- 9)
- at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
- at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.jav
- a:1079)
- at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.j
- ava:1002)
- at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:506
- )
- at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
- at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java
- :324)
- at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(Lifecycl
- eSupport.java:142)
- at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
- at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
- at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
- at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463
- )
- at org.apache.catalina.core.StandardService.start(StandardService.java:5
- 25)
- at org.apache.catalina.core.StandardServer.start(StandardServer.java:754
- )
- at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
- java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
- sorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
- at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
- 2015-3-20 15:22:39 org.apache.catalina.core.StandardContext start
- 严重: Error listenerStart
再来看看相关源码:
- public class GateWayMonitorListener implements ServletContextListener, ApplicationContextAware
- {
- /**
- * 设定两个线程,一个用来定期发送巡检短信;另一个定期执行三大运营商网关监控。
- */
- public static ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
- public void contextInitialized(ServletContextEvent event)
- {
- // 网关监测
- GateWayMonitorListener.service.scheduleWithFixedDelay(new MonitorTask(), 60, MonitorConfigCache.lastPollingIntervalSecond, TimeUnit.SECONDS);
- // 定时每天固定时间发送短信
- GateWayMonitorListener.service.scheduleAtFixedRate(new EveryDaySmsTask(), calculateIntialDelay(), GateWayMonitorListener.ONE_DAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
- }
- }
- /**
- * 按新时间间隔重新设置定时任务。
- *
- * @param interval
- */
- public static synchronized void resetMonitorTaskInterval()
- {
- // 关闭老的线程池
- GateWayMonitorListener.service.shutdownNow();
- try
- {
- GateWayMonitorListener.service.awaitTermination(60, TimeUnit.SECONDS);
- }
- catch (InterruptedException e)
- {
- log.warn("InterruptedException when shutdown old threadPool", e);
- }
- catch (Exception e)
- {
- log.error("other exception when shutdown old threadPool", e);
- }
- GateWayMonitorListener.service = Executors.newScheduledThreadPool(2);
- // 重新设置定时任务。
- …
- }
没有列出的还有另一个类会定时重新加载定时任务的配置文件,如果配置文件修改了定时任务执行的时间设置,则重新配置定时任务,起到热加载配置文件的目的。也就是会调用resetMonitorTaskInterval()方法。
二、 问题分析
Tomcat一启动就报错RejectedExecutionException,
(1)根据jdk描述何时回抛出这个异常:if the task cannot be scheduled for execution,只是说任务在不能被加入线程池时会抛出这个异常,不够明确。
(2)进一步分析什么时候线程池不能加入线程来执行,如果不是线程池还未被初始化好,线程池已满且策略是超过的会被拒绝外,就是线程池被shutdown了。Tomcat一启动就报错,而且线程池是在最上面static的,那应该就是被shutdown了。查看是否有哪里调用shutdown方法了。
(3)再分析,果然在另一个线程处会调用重新设置线程池的方法resetMonitorTaskInterval(),而且里面调用了shutdown。问题找到了,第一次读配置文件时就触发了重新设置定时任务。这是不行滴。。第一次只算是初始化,后面发现变更才应该重设线程池。但一定要控制同步,保证shutdown之后没有再往旧线程池中加入定时任务。
三、 问题解决
控制线程池的shutdown调用,调用后不能再往线程池里加入线程。
原文地址:http://zoroeye.iteye.com/blog/2194390
<线程池-定时任务> ScheduledExecutorService之shutdown引发的RejectedExecutionException问题的更多相关文章
- 一次Java线程池误用(newFixedThreadPool)引发的线上血案和总结
一次Java线程池误用(newFixedThreadPool)引发的线上血案和总结 这是一个十分严重的线上问题 自从最近的某年某月某天起,线上服务开始变得不那么稳定(软病).在高峰期,时常有几台机器的 ...
- 【转】一次Java线程池误用(newFixedThreadPool)引发的线上血案和总结
[转]原文链接:https://cloud.tencent.com/developer/article/1497826 这是一个十分严重的线上问题 自从最近的某年某月某天起,线上服务开始变得不那么稳定 ...
- JAVA线程池ScheduledExecutorService周期性地执行任务 与单个Thread周期性执行任务的异常处理
本文记录: 1,使用ScheduledExecutorService的 scheduleAtFixedRate 方法执行周期性任务的过程,讨论了在任务周期执行过程中出现了异常,会导致周期任务失败. 2 ...
- JUC线程池之 线程池的5种状态:Running, SHUTDOWN, STOP, TIDYING, TERMINATED
线程池有5种状态:Running, SHUTDOWN, STOP, TIDYING, TERMINATED. 线程池状态定义代码如下: private final AtomicInteger ctl ...
- Java 线程池原理分析
1.简介 线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销.在应用上,线程池可应用在后端相关服务中.比如 Web 服务器,数据库服务器等 ...
- Java线程池原理解读
引言 引用自<阿里巴巴JAVA开发手册> [强制]线程资源必须通过线程池提供,不允许在应用中自行显式创建线程. 说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销 ...
- Java线程池基础
目录: 一.线程池概述 二.线程池参数 三.线程池的执行过程 四.线程池的主要实现 五.线程池的使用 六.线程池的正确关闭方式 七.线程池参数调优 一.线程池概述 1.线程池类 目前线程池类一般有两个 ...
- 线程池 | Java多线程,彻底搞懂线程池
熟悉Java多线程编程的同学都知道,当我们线程创建过多时,容易引发内存溢出,因此我们就有必要使用线程池的技术了. 最近看了一些相关文章,并亲自研究了一下源码,发现有些文章还是有些问题的,所以我也总结了 ...
- Java并发指南12:深度解读 java 线程池设计思想及源码实现
深度解读 java 线程池设计思想及源码实现 转自 https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&utm_ ...
随机推荐
- 7.C# 多态的实现
C# 多态的实现 封装.继承.多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了.我一直认为学习OO的最好方法就是结合实践,封装.继承在实 ...
- 下拉列表控件实例 ComboBoxControl
下拉列表控件实例 书:151页 <?xml version="1.0" encoding="utf-8"?> <s:Application x ...
- 通过Response下载。
之前一直在找js下载的插件,后来发现下载必须通过java后台处理,什么write(),open(),close()之类的方法.如果直接是通过<a>标签倒是简单的,直接将路径摆放在上面就可以 ...
- JavaScript原型规则和实例
var arr = [] // var arr = new Array() var obj = {} // var obj = new Object() function fn() {} // var ...
- Sublime text3 经常出现 “ There are no packages avaliable for installation” 解决方法
对应这个问题,一开始在度娘上找到很多答案,包括将json文件放在本地然后通过 package setting 更改的,发现其实不好使,原因未知. 后来测试了在hosts文件添加sublime text ...
- LeetCode104.二叉树最大深度
给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7], ...
- Javascript-购物车结算-案例
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- pandas常用函数
1. df.head(n): 显示数据前n行,不指定n,df.head则会显示所有的行 2. df.columns.values获取所有列索引的名称 3. df.column_name: 直接获取列c ...
- scrapy 参考教程及安装
scrapy 参考教程及安装环境: win7/10 64bit, python 3.6.x教程: http://python.jobbole.com/86405/安装过程0. 预先安装 VC14 64 ...
- asp.net GridView增加删除功能
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { string id ...