1、Timer管理延时任务的缺陷

a、以前在项目中也经常使用定时器,比如每隔一段时间清理项目中的一些垃圾文件,每个一段时间进行数据清洗;然而Timer是存在一些缺陷的,因为Timer在执行定时任务时只会创建一个线程,所以如果存在多个任务,且任务时间过长,超过了两个任务的间隔时间,会发生一些缺陷:下面看例子:

Timer的源码:

public class Timer {

/**

* The timer task queue.  This data structure is shared with the timer

* thread.  The timer produces tasks, via its various schedule calls,

* and the timer thread consumes, executing timer tasks as appropriate,

* and removing them from the queue when they're obsolete.

*/

private TaskQueue queue = new TaskQueue();

/**

* The timer thread.

*/

private TimerThread thread = new TimerThread(queue);

TimerThread是Thread的子类,可以看出内部只有一个线程。下面看个例子:

package com.zhy.concurrency.timer;

import java.util.Timer;

import java.util.TimerTask;

public class TimerTest

{

private static long start;

public static void main(String[] args) throws Exception

{

TimerTask task1 = new TimerTask()

{

@Override

public void run()

{

System.out.println("task1 invoked ! "

+ (System.currentTimeMillis() - start));

try

{

Thread.sleep(3000);

} catch (InterruptedException e)

{

e.printStackTrace();

}

}

};

TimerTask task2 = new TimerTask()

{

@Override

public void run()

{

System.out.println("task2 invoked ! "

+ (System.currentTimeMillis() - start));

}

};

Timer timer = new Timer();

start = System.currentTimeMillis();

timer.schedule(task1, 1000);

timer.schedule(task2, 3000);

}

}

定义了两个任务,预计是第一个任务1s后执行,第二个任务3s后执行,但是看运行结果:

task1 invoked ! 1000

task2 invoked ! 4000

task2实际上是4后才执行,正因为Timer内部是一个线程,而任务1所需的时间超过了两个任务间的间隔导致。下面使用ScheduledThreadPool解决这个问题:

package com.zhy.concurrency.timer;

import java.util.TimerTask;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExecutorTest

{

private static long start;

public static void main(String[] args)

{

/**

* 使用工厂方法初始化一个ScheduledThreadPool

*/

ScheduledExecutorService newScheduledThreadPool = Executors

.newScheduledThreadPool(2);

TimerTask task1 = new TimerTask()

{

@Override

public void run()

{

try

{

System.out.println("task1 invoked ! "

+ (System.currentTimeMillis() - start));

Thread.sleep(3000);

} catch (Exception e)

{

e.printStackTrace();

}

}

};

TimerTask task2 = new TimerTask()

{

@Override

public void run()

{

System.out.println("task2 invoked ! "

+ (System.currentTimeMillis() - start));

}

};

start = System.currentTimeMillis();

newScheduledThreadPool.schedule(task1, 1000, TimeUnit.MILLISECONDS);

newScheduledThreadPool.schedule(task2, 3000, TimeUnit.MILLISECONDS);

}

}

输出结果:

task1 invoked ! 1001

task2 invoked ! 3001

符合我们的预期结果。因为ScheduledThreadPool内部是个线程池,所以可以支持多个任务并发执行。

2、Timer当任务抛出异常时的缺陷

如果TimerTask抛出RuntimeException,Timer会停止所有任务的运行:

package com.zhy.concurrency.timer;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

public class ScheduledThreadPoolDemo01

{

public static void main(String[] args) throws InterruptedException

{

final TimerTask task1 = new TimerTask()

{

@Override

public void run()

{

throw new RuntimeException();

}

};

final TimerTask task2 = new TimerTask()

{

@Override

public void run()

{

System.out.println("task2 invoked!");

}

};

Timer timer = new Timer();

timer.schedule(task1, 100);

timer.scheduleAtFixedRate(task2, new Date(), 1000);

}

}

上面有两个任务,任务1抛出一个运行时的异常,任务2周期性的执行某个操作,输出结果:

task2 invoked!

Exception in thread "Timer-0" java.lang.RuntimeException

at com.zhy.concurrency.timer.ScheduledThreadPoolDemo01$1.run(ScheduledThreadPoolDemo01.java:24)

at java.util.TimerThread.mainLoop(Timer.java:512)

at java.util.TimerThread.run(Timer.java:462)

由于任务1的一次,任务2也停止运行了。。。下面使用ScheduledExecutorService解决这个问题:

package com.zhy.concurrency.timer;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolDemo01

{

public static void main(String[] args) throws InterruptedException

{

final TimerTask task1 = new TimerTask()

{

@Override

public void run()

{

throw new RuntimeException();

}

};

final TimerTask task2 = new TimerTask()

{

@Override

public void run()

{

System.out.println("task2 invoked!");

}

};

ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

pool.schedule(task1, 100, TimeUnit.MILLISECONDS);

pool.scheduleAtFixedRate(task2, 0 , 1000, TimeUnit.MILLISECONDS);

}

}

代码基本一致,但是ScheduledExecutorService可以保证,task1出现异常时,不影响task2的运行:

task2 invoked!

task2 invoked!

task2 invoked!

task2 invoked!

task2 invoked!...

3、Timer执行周期任务时依赖系统时间

Timer执行周期任务时依赖系统时间,如果当前系统时间发生变化会出现一些执行上的变化,ScheduledExecutorService基于时间的延迟,不会由于系统时间的改变发生执行变化。

上述,基本说明了在以后的开发中尽可能使用ScheduledExecutorService(JDK1.5以后)替代Timer。

java timer异常_JAVA Timer的缺陷以及解决办法相关推荐

  1. java 线程安全问题_java线程安全问题原因及解决办法

    1.为什么会出现线程安全问题 计算机系统资源分配的单位为进程,同一个进程中允许多个线程并发执行,并且多个线程会共享进程范围内的资源:例如内存地址.当多个线程并发访问同一个内存地址并且内存地址保存的值是 ...

  2. java jce配置_java JCE 不限密钥长度解决办法

    ()转自http://opensourceforgeeks.blogspot.com/2014/09/how-to-install-java-cryptography.html 另外,在StackOv ...

  3. java 到异常_java编程中遇到的异常以及异常的一些处理

    n 异常的概念 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户? 比如除法运算.读写文件操作,都可能 ...

  4. Win7下运行小雨伞tinyumbrella-5/6异常:Exception in thread AWT-EventQueue-0解决办法

    [转]Win7下运行小雨伞tinyumbrella-5/6异常:Exception in thread "AWT-EventQueue-0"解决办法 来自威锋网 原文链接:http ...

  5. java getparameter 乱码,request.getParameter()取值乱码解决办法

    当前位置:我的异常网» Java Web开发 » request.getParameter()取值乱码解决办法 request.getParameter()取值乱码解决办法 www.myexcepti ...

  6. com/opensymphony/xwork2/spring/SpringObjectFactory.java:220:-1问题出现的原因及解决办法

    转自:https://blog.csdn.net/shinchan_/article/details/37818927 com/opensymphony/xwork2/spring/SpringObj ...

  7. ANDROID开发java.lang.NoClassDefFoundError: com.baidu.location.LocationClient的解决办法

     ANDROID开发java.lang.NoClassDefFoundError: com.baidu.location.LocationClient的解决办法 java.lang.NoClassDe ...

  8. ios阴阳是不显示服务器,阴阳师IOS登录异常怎么办 苹果不能正常登录解决办法...

    在11月11日阴阳师新版本更新后,许多苹果IOS服务器的玩家反馈登录异常,经常登录不进游戏,对此4399挽歌为大家带来具体解决方法,一起来看看阴阳师IOS登录异常怎么办 苹果不能正常登录解决办法吧! ...

  9. java: JDK isn‘t specified for module ‘maven-junit41‘解决办法

    java: JDK isn't specified for module 'maven-junit41'解决办法. 在单元测试中出现错误:java: JDK isn't specified for m ...

  10. Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority 的解决办法

    问题概述: 使用 Spring Boot-2.0.3 进行项目开发,在配置 Druid 数据监控时,遇到缺包的问题,测试连接操作时报错,导致测试一直无法通过,部分信息如下: Caused by: ja ...

最新文章

  1. 函数重载和覆盖(重写)的区别
  2. 【问链财经-区块链基础知识系列】 第二十七课 区块链与分布式账本的异同
  3. 【已解决】tomcat启动不成功(点击startup.bat闪退)的解决办法
  4. 音视频技术开发周刊 | 154
  5. 如何解析json字符串及返回json数据到前端
  6. 11-11 又是一年光棍节!
  7. 使用未初始化的内存是什么意思_他们都说JVM能实际使用的内存比-Xmx指定的少?这是为什么呢...
  8. Kotlin实战【四】迭代事物:while和for
  9. 如何在js中实现html语言,如何使用脚本标签将JavaScript插入HTML
  10. java win10_java下载64位win10-javawin10 64位下载8.0.1210.13官方版-西西软件下载
  11. PaddleOCR二次全流程——2.使用StyleText合成图片
  12. jq ui.dialog.js简介
  13. python数据分析之朴素贝叶斯实践
  14. AWD竞赛脚本大全——从攻击到防御
  15. 2022年最新文本生成图像研究 开源工作速览(Papers with code)
  16. web应用基本框架图
  17. 多媒体基础学习笔记:MPEG-7
  18. 因测试和登录软件微信被封,淘客必须注意,微信封号原则是什么?
  19. 中国首届DFMA降本设计峰会
  20. 【ES8系列】String 补白、格式化

热门文章

  1. cortex M3/4 内部总线
  2. 打印端口用计算机名,如何设置打印机端口,教您设置电脑打印机端口
  3. python什么情况下要加eval_python 为什么说eval要慎用?使用eval 带来的潜在风险?什么情况下使用eval?...
  4. vue实现农历日期选择器
  5. 计算机自动关机原理,电脑自动关机什么原因 电脑自动关机是怎么回事
  6. 学计算机投影仪定义,一种计算机信息技术教学用投影仪的制作方法
  7. CentOS 7.5 安装MySQL教程
  8. Java:spring Value注解用法详解
  9. 【Java算法学习】鸡兔同笼问题
  10. 阿里云云原生数据湖体系全解读——数据湖构建 数据导入