java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java Timer和Timertask的关系

java中的Timer和Timertask的关系解读

作者:健康平安的活着

本文详细介绍了Java中的Timer和TimerTask类,包括它们之间的关系、API的使用方法、注意事项以及操作案例,Timer是一个调度器,而TimerTask是具体的任务类,Timer仅对应一个线程,不保证任务执行的精确性,但线程安全,一个Timer可以调度多个TimerTask

一 time和timertask的关系

1.1 timer和timertask关系

1.Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个类;

2.Timer和TimerTask成对出现,Timer是定时器,TimerTask是定时任务。换句话说,定时任务TimerTask是给定时器Timer执行的具体任务。TimerTask实现Runnable接口的run方法。

Java的定时器Timer和定时任务TimerTask应用以及原理

3.每一个Timer仅对应唯一一个线程。Timer不保证任务执行的十分精确。Timer类的线程安全的。

4.一个Timer可以调度任意多个TimerTask,所有任务都存储在一个队列中顺序执行,如果需要多个TimerTask并发执行,则需要创建两个多个Timer。

一个Timer可以执行多个TimerTask,但一个TimerTask只能被一个Timer使用(这和schedule中校验TimerTask的状态有关,TimerTask的生命周期(由不同的状态确定))。

简单的说Timer中有两个核心部分:

TimerThread是时间线程,控制TaskQueue中TimerTask的执行;

TaskQueue是一个工具类,管理TimerTask数组

1.2 timer的api

无参构造方法,简单通过Tiemer为前缀构造一个线程名称

有参构造方法,传入了是否为后台线程,后台线程当且仅当进程结束时,自动注销掉。

1.3 终止Timer线程

默认情况下,创建的timer线程会一直执行,主要有下面四种方式来终止timer线程:

1) 调用Timer.cancle()方法。可以在程序任何地方调用,甚至在TimerTask中的run方法中调用;

2) 创建Timer时定义位daemon守护线程,使用new Timer(true)语句;

3) 设置Timer对象为null,其会自动终止;????有待考证

4) 调用System.exit方法,整个程序终止。

1.4 timer注意事项

1) Timer线程不会捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程。如果Timer线程中存在多个计划任务,其中一个计划任务抛出未检查的异常,则会引起整个Timer线程结束,从而导致其他计划任务无法得到继续执行。  

2) Timer线程时基于绝对时间(如:2023/02/14 16:06:00),因此计划任务对系统的时间的改变是敏感的。

3) Timer是单线程,如果某个任务很耗时,可能会影响其他计划任务的执行。

因此,JDK1.5以上建议使用ScheduledThreadPoolExecutor来代替Timer执行计划任务。

二 操作案例

2.1 一个Timer执行多个Task,堵塞现象

package com.ljf.lockdemo.task.timerdemo;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @ClassName: TestDemo2
 * @Description: TODO
 * @Author: admin
 * @Date: 2024/03/02 11:30:06 
 * @Version: V1.0
 **/
public class TestDemo2 {
    public static void main(String[] args) {
        TimerTask task1=new TimerTask() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println("[当前线程是:"+name+",执行定时任务1:"+System.currentTimeMillis()+"]");
            }
        };

        TimerTask task2=new TimerTask() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String name = Thread.currentThread().getName();
                System.out.println("[当前线程是:"+name+",执行定时任务2:"+System.currentTimeMillis()+"]");
            }
        };


        Timer timer=new Timer();
        timer.schedule(task2,10000);
        timer.schedule(task1,100,3000);

    }
}

结果:

2.2 异常现象

现象操作,在timetask2中,模拟一个除以0的算术异常。

强调:在执行任何一个任务的run方法时,一旦run抛出了异常,Timer线程就会退出,从而所有定时任务都会被取消。如果希望各个定时任务互不干扰,一定要在run方法内捕获所有异常。

这里catch的异常为:integerrupteException

改成Exceptione 如图

启动两个timer

总结

1个timer没有cancel掉,使用的一直是一个线程id;1个timer关闭后,再每次new后,使用的线程id都不相同。

在1个timer中,开启两个timetask;这个两个timertask串行执行,单线程;使用的线程id是相同的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文