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)


相关推荐

  • ShellExecute, WinExec, CreateProcess区别

    ShellExecute, WinExec, CreateProcess区别ShellExecute  ShellExecute的功能是运行一个外部程序(或者是打开一个已注册的文件、打开一个目录、打印一个文件等等),并对外部程序有一定的控制。  有几个API函数都可以实现这些功能,但是在大多数情况下ShellExecute是更多的被使用的,同时它并不是太复杂。  ShellExecute函数原型及参数含义如下:  ShellExecute(  HWNDhwnd,…

  • SaveFileDialog_save文件用什么修改

    SaveFileDialog_save文件用什么修改c#获取要保存文件的对话框,用SaveFileDialog类。具体用法很简单分享一下吧,对于初学者可能有用//可能要获取的路径名stringlocalFilePath=“”,fileNameExt=“”,newFileName=“”,FilePath=“”;SaveFileDialogsaveFileDialog=newSaveFileDialog();//设置文件类型//书写规则例如:txtfiles(.txt)|.txtsaveFileDialog.Filter

  • 【python】Excel转json「建议收藏」

    【python】Excel转json「建议收藏」importxlrd,json,osdata=xlrd.open_workbook(“working_file.xls”)public=[]tables=[(excelName,data.sheet_by_name(excelName))forexcelNameindata.sheet_names()]#表由多个相同的表,数据为两列组成filePath=”picture_folder_path”#图片路径forindex,dataSetintabl

  • tomcat路径怎么找_tomcat项目路径

    tomcat路径怎么找_tomcat项目路径Maven配置覆盖内嵌tomcat虚拟映射路径

  • 图集谷-写真集-爬虫-2.0

    图集谷-写真集-爬虫-2.0图集谷写真集python爬虫

  • 计算机网络各协议总结_计算机网络实验总结

    计算机网络各协议总结_计算机网络实验总结计算机网络协议全面总结一、OSI七层协议物理层:很久很久以前,那时候还没有现在的外星人超级电脑,或者华为的P30。比较调皮的小明想要把自己机器上写好的一些个人游戏心得(如何玩好王者农药)发给小红(校花),希望博得芳心。小明个人比较勤,游戏总结心得总结的比较详细(大概有100M)。但是到底怎么才能从自己的机器上传给小红的机器呢,进过一番打听,他发现远在太平洋另一端的科学家已经发明了一种技术物…

发表回复

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

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