timer定时器用法_定时器怎么调时间

timer定时器用法_定时器怎么调时间在JDK类库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。此类也常用来做一下周期性同步工作,代替它的有quartz、SpringTask。Timer类的主要作用是设置计划

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

  在JDK类库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。此类也常用来做一下周期性同步工作,代替它的有quartz、SpringTask。Timer类的主要作用是设置计划任务,但封装任务的类是TimerTask类(实际该类是一个抽象类,执行任务的代码要放在该类的子类中)。Timer类的主要方法列表如下:

构造方法

timer定时器用法_定时器怎么调时间

 

成员方法:

timer定时器用法_定时器怎么调时间

 

Timer内部维护一个  TimerThread   线程,而且线程名字与Thread类一样,默认用一个静态成员变量进行生成全局序列。

public class Timer {

    private final TaskQueue queue = new TaskQueue();

    /**
     * The timer thread.
     */
    private final TimerThread thread = new TimerThread(queue);

    /**
     * This ID is used to generate thread names.
     */
    private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);

 

TimerThread的run方法中while循环获取TaskQueue中的task并且执行任务(mainLoop中执行执行task.run()方法–相当于同步调用)

class TimerThread extends Thread {
 
    boolean newTasksMayBeScheduled = true;

    private TaskQueue queue;

    TimerThread(TaskQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            mainLoop();
        } finally {
            synchronized(queue) {
                newTasksMayBeScheduled = false;
                queue.clear();  // Eliminate obsolete references
            }
        }
    }

    /**
     * The main timer loop.  (See class comment.)
     */
    private void mainLoop() {
        while (true) {
      。。。。。。
        }
    }

 

 TaskQueue用于存放TimerTask任务(内部维护一个TimerTask数组)。

class TaskQueue {

    private TimerTask[] queue = new TimerTask[128];

  。。。

 

TimerTask是一个继承Runnable接口的抽象类:

public abstract class TimerTask implements Runnable {

    final Object lock = new Object();
。。。

TimerTask有一个cancel方法用于将当前任务从任务队列删除。(也就是队列中不会执行该任务,如果正在执行中调用该方法会执行完毕)

    public boolean cancel() {
        synchronized(lock) {
            boolean result = (state == SCHEDULED);
            state = CANCELLED;
            return result;
        }
    }

 

 1. Sschedule(task, Date)的用法

  此方法用于在指定的时间执行一次task。默认的执行完毕不会结束线程,因为timer的成员属性thread默认是非守护线程,而且其run方法中通过轮询同步调用task的run()方法。

例子1:一个简单的测试:(在未来时间执行一次任务—会到指定之间执行run()方法)

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo1.class);

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo1 task = new Demo1();
        Date runtime = new Date(System.currentTimeMillis() + 5000);
        timer.schedule(task, runtime);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {}", Thread.currentThread().getName(), i + "");
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:(可以看到先打印的end,后执行的run中方法,并且执行完毕之后进程并未销毁。也验证了是新开一个线程进行操作,并且线程是非守护线程)

timer定时器用法_定时器怎么调时间

 

 查看源码:

    public Timer() {
        this("Timer-" + serialNumber());
    }
    public Timer(String name) {
        thread.setName(name);
        thread.start();
    }

 

 如果将上面Timer中的TimerThread设为守护线程将不会执行run中方法,因为main线程执行完毕,没有非守护线程的存在,所以守护线程也销毁导致进程销毁。

另一种办法是等待执行完之后调用timer.cancel()

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo1 task = new Demo1();
        Date runtime = new Date(System.currentTimeMillis() + 5000);
        timer.schedule(task, runtime);
        LOGGER.info("end ");
        
        Thread.sleep(6*1000);
        timer.cancel();
    }

结果:

timer定时器用法_定时器怎么调时间

 

 例子2:多个任务在之前的时间执行—(线性顺序执行多个task,是从queue中获取task然后执行,如果时间早于当前时间会马上执行任务)

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo1.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo1 task = new Demo1("t1");
        Demo1 task2 = new Demo1("t2");
        Date runtime = new Date(System.currentTimeMillis() - 5000);
        timer.schedule(task, runtime);
        timer.schedule(task2, runtime);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo1(String name) {
        super();
        this.name = name;
    }
}

结果:

timer定时器用法_定时器怎么调时间

 2. Sschedule(TimerTask task, Date firsttime,long period)的用法

   此方法用于在指定的时间执行一次之后任务之后,在指定的period的时间间隔后不停的执行任务

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo2 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo2.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo2 task = new Demo2("t1");
        Demo2 task2 = new Demo2("t2");
        Date runtime = new Date(System.currentTimeMillis() + 5000);
        timer.schedule(task, runtime, 20 * 1000);
        timer.schedule(task2, runtime, 20 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo2(String name) {
        super();
        this.name = name;
    }
}

结果:(时间间隔是从任务开始执行计算的,也就是从当前任务执行的开始时间到下次任务开始时间的间隔是20秒)

timer定时器用法_定时器怎么调时间

 3. Shedule(TimerTask task, long delay)的用法

   以当前时间为参考,在延迟指定的秒数后执行一次性任务;如果延迟时间是负数会抛出IllegalArgumentException异常。

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo3 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo3.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo3 task = new Demo3("t1");
        timer.schedule(task, 2 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo3(String name) {
        super();
        this.name = name;
    }
}

 结果:(执行完线程不会关闭)

timer定时器用法_定时器怎么调时间

 4. Shedule(TimerTask task, long delay,long period)的用法

   以当前时间为参考,在延迟指定的秒数后第一次执行任务;如果延迟时间是负数会抛出IllegalArgumentException异常。并且在period后重复执行任务,执行时间是从上次任务结束时间开始计算。凡是带period的都会在时间间隔后重复执行。

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo4 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo4.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo4 task = new Demo4("t1");
        timer.schedule(task, 2 * 1000, 10 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo4(String name) {
        super();
        this.name = name;
    }
}

结果

timer定时器用法_定时器怎么调时间

 

 5. sheduleAtFixedRate(TimerTask task, Date firstTime,long period)的用法

   方法schedule和scheduleAtFixedRate都会按顺序执行,所以不要考虑非线程安全的情况。

  在有延时和没有延时的情况下,周期性的任务的下次任务开始时间都是相对于上次任务的开始时间进行延迟(这个在并发编程书中说的是有延迟的情况下相对于结束时间,但是自己测的是相对于开始时间)

  schedule和scheduleAtFixedRate的区别在于,如果指定开始执行的时间在当前系统运行时间之前,scheduleAtFixedRate会把已经过去的时间也作为周期执行,而schedule不会把过去的时间算上

1.scheduleAtFixedRate(TimerTask task,long delay,long period)   有延迟,下次任务相对于上次任务的开始时间开始执行:

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo5 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo5.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo5 task = new Demo5("t1");
        timer.scheduleAtFixedRate(task, 2 * 1000, 10 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo5(String name) {
        super();
        this.name = name;
    }
}

结果:

timer定时器用法_定时器怎么调时间

 

2.scheduleAtFixedRate(TimerTask task,Date startTime,long period)   指定开始执行的时间在当前系统运行时间之前,会把已经过去的时间也作为周期执行

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo6 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo6.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo6 task = new Demo6("t1");
        timer.scheduleAtFixedRate(task, new Date(System.currentTimeMillis() - 5000), 10 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo6(String name) {
        super();
        this.name = name;
    }
}

结果:(第二次任务把之前的5秒钟也包含在延迟时间内)

timer定时器用法_定时器怎么调时间

 

补充:

1.TimerTask有一个cancel方法用于将当前任务从任务队列删除。(也就是队列中不会执行该任务,如果正在执行中调用该方法会执行完毕)

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo2 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo2.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo2 task = new Demo2("t1");
        Demo2 task2 = new Demo2("t2");
        Date runtime = new Date(System.currentTimeMillis() + 5000);
        timer.schedule(task, runtime, 20 * 1000);
        timer.schedule(task2, runtime, 20 * 1000);
        LOGGER.info("end ");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            if (name.equals("t1")) {
                this.cancel();
            }
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo2(String name) {
        super();
        this.name = name;
    }
}

结果:(t1任务被删除)

timer定时器用法_定时器怎么调时间

 

 2.Timer的cancel方法用于清空所有任务队列(如果有任务正在执行会等任务执行完清空;有时候不一定会停掉,因为cancel方法不一定能抢到queue对象的锁)

package cn.qlq.thread.fourteen;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo2 extends TimerTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo2.class);
    private String name;

    public static void main(String[] args) throws InterruptedException {
        LOGGER.info("start ");
        Timer timer = new Timer();
        Demo2 task = new Demo2("t1");
        Demo2 task2 = new Demo2("t2");
        Date runtime = new Date(System.currentTimeMillis());
        timer.schedule(task, runtime, 20 * 1000);
        timer.schedule(task2, runtime, 20 * 1000);
        LOGGER.info("end ");
        Thread.sleep(2 * 1000);
        timer.cancel();
        LOGGER.info("timer cancel");
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            LOGGER.info("threadName -> {},value -> {},taskName->{}", Thread.currentThread().getName(), i + "", name);
            if (name.equals("t1")) {
                this.cancel();
            }
            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Demo2(String name) {
        super();
        this.name = name;
    }
}

结果:

timer定时器用法_定时器怎么调时间

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168301.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • SPSSlogistic回归分析_logistic回归分析表格解读

    SPSSlogistic回归分析_logistic回归分析表格解读spsslogistic回归分析结果如何分析如何用spss17.0进行二元和多元logistic回归分析一、二元logistic回归分析二元logistic回归分析的前提为因变量是可以转化为0、1的二

  • matlab微分方程组_matlab求微分方程特解

    matlab微分方程组_matlab求微分方程特解主要内容:matlab参数识别应用,主要适用于微分方程、微分方程组参数识别、simulink模型参数识别,领域不限。1使用matlab识别微分方程参数以及微分方程组(多个微分方程)参数2使用matlab调用simulink并识别simulink模型的参数(m函数与simulink交互)内容为本人在学习过程中总结的知识,拿出来与大家分享,希望大家多多讨论。下边贴出一部分源码,其它完整内容在附件的…

  • 解决Win10系统图标变白[通俗易懂]

    解决Win10系统图标变白[通俗易懂]解决因为安装路径文件名更改导致图标变白

    2022年10月19日
  • 关于三极管的理解—根据IC符号简易迅速判断三极管导通情况

    关于三极管的理解—根据IC符号简易迅速判断三极管导通情况  很不幸,开始写博客的第一天就被师兄批评了。其实很对不起师兄,当年在大学学习模拟电路的时候我不太认真,那时候天天忙着和女朋友吃吃喝喝。。所以对于三极管的各种性质与基本运用场景缺乏较深的理解,仅仅只是知道导通、截止等几种判断方式而已。今天在设计电路时涉及到了运用三极管驱动光耦器件,以及通过三极管来驱动蜂鸣器等操作,在三极管的选材和设计上出现了低级的失误。检讨完毕后,翻出当年的模电书,配…

  • Linux磁盘分区详解

    Linux磁盘分区详解文章目录预备知识磁道扇区柱面簇文件系统本地存储设备的识别设备的挂载和卸载设备名称设备挂载磁盘分区具体分区步骤swap分区管理概念新建swap分区删除swap分区磁盘配额quota配额概念quota如何设定配额quota的限额磁盘加密cryptsetup概念加密方法加密设备开机自动挂载删除加密后的虚拟设备预备知识在开始之前,先了解一些基础知识。磁道硬盘被一圈圈分成18等分的同心圆,这些同心…

  • chrome调试appweb_调试应用是什么意思

    chrome调试appweb_调试应用是什么意思googleDevice使用

    2022年10月26日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号