<线程池-定时任务> 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_ ...
随机推荐
- centos7挂载新加4T硬盘到/home目录
以下操作均在root环境下运行. 1.查看硬盘 # fdisk -l 发现硬盘为/dev/sdb 大小4T 2.如果此硬盘以前有过分区,则先对磁盘格式化: # mkfs -t ext4 /dev/sd ...
- xcode 各版本下载地址及其它工具下载地址
官方下载地址:https://developer.apple.com/downloads/
- DataGridView控件用法一:数据绑定
使用DataGridView控件,可以显示和编辑来自多种不同类型的数据源的表格数据. 将数据绑定到DataGridView控件非常简单和直观,在大多数情况下,只需设置DataSource属性即可.在绑 ...
- laravel orm
###多对多关系 多对多关系和之前的关系完全不一样,因为多对多关系可能出现很多冗余数据,用之前自带的表存不下了. 我们定义两个模型:Article 和 Tag,分别表示文章和标签,他们是多对多的关系. ...
- [10]Windows内核情景分析---中断处理
中断处理 每个cpu有一张中断表,简称IDT. IDT的整体布局:[异常->空白->5系->硬](推荐采用7字口诀的方式重点记忆) 异常:前20个表项存放着各个异常的描述符(IDT表 ...
- Python全栈-库的操作
一.系统数据库 安装数据库系统后,系统自带的数据库.通过mysql客户端连接数据库系统后,使用show命令可查看系统中存在的所有库: mysql> show databases; +------ ...
- IO model
上节的问题: 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么确定IO操作完了? 很多程序员可能会考虑使用“线程池”或“连接池”.“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程, ...
- 【Hadoop学习之六】MapReduce原理
一.概念MapReduce:"相同"的key为一组,调用一次reduce方法,方法内迭代这一组数据进行计算 块.分片.map.reduce.分组.分区之间对应关系block > ...
- 基于word2vec训练词向量(二)
转自:http://www.tensorflownews.com/2018/04/19/word2vec2/ 一.基于Hierarchical Softmax的word2vec模型的缺点 上篇说了Hi ...
- LDA模型了解及相关知识
什么是LDA? LDA是基于贝叶斯模型的,涉及到贝叶斯模型离不开“先验分布”,“数据(似然)”和"后验分布"三块.贝叶斯相关知识:先验分布 + 数据(似然)= 后验分布. 贝叶斯模 ...