<线程池-定时任务> 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_ ...
随机推荐
- cocos2d JS touch屏幕点击事件监听 cc.EventListener.TOUCH
var self = this; this.touchListener = cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY ...
- python No tests were found问题解决方法
由于刚刚开始用python去写测试接口框架,在写的过程中遇到No tests were found问题 原因:python中unittest框架是以Test开头的方法,所以定义方法或类不能以Test开 ...
- shell基础:用户自定义变量
- 本地tp项目上传服务器报runtime/cache错误
很简单,给runtime权限777 就好了 chmod -r 777 runctime
- RSA 加解密 秘钥对说明
rsa非对称加密, 加解密需要不同的秘钥,称作一对. rsa加解密分两种,第一:公钥加密私钥解密.第二:私钥加密公钥解密. 需要注意的是,公加私解得到的密文是变化的,而私加公解的得到的密文是固定的. ...
- 等比数列二分求和(logn复杂度)
看完这个之后,感觉数学简直太厉害了 转载自:http://blog.csdn.net/acdreamers/article/details/7851144 今天我们学习如何有效地求表达式的值.对于这个 ...
- java生成随机六位数的验证码&随机生成十位数ValidCode码,用于邮件的验证&检查是不是符合为合法的中国的手机号码
package com.demo.test1; import java.security.NoSuchAlgorithmException; import java.security.SecureRa ...
- OBO文件格式1.2
该文件每一行都是一个键值对,基本格式为: 键: 值!注释 总体结构: 文件头 !包含若干行总体说明 词条1 ![词条类型]占第一行,后跟若干行说明 词条2 ! ...
- Groovy常用编程知识点简明教程
概述 Groovy 是一门基于JVM的动态类型语言,可以与 Java 平台几乎无缝融合(与Java代码一样编译成字节码). 使用 Groovy ,可以增强 Java 应用的灵活性和可扩展性,提升开发效 ...
- HIBERNATE与 MYBATIS的对比
我是一名java开发人员,hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践中也应用过,现在对hibernate和mybatis做一下对比,便于大家更好的理解和 ...