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定时器用法_定时器怎么调时间

 

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Boltzmann机详解

    Boltzmann机详解基于热力学的随机型神经网络–Boltzmann机1.模拟退火算法我们知道,Hopfield神经网络拥有联想记忆的能力,这也是对生物神经网络的一种模拟。但是,Hopfield神经网络也和BP神经网络一样,有一个致命的缺陷:只能找到局部最优解,而无法沿着梯度上升的方向在全局的角度寻求全局最优解。为了解决这个问题,1983年,Kirkpatrick等提出了模拟退火算法(SA)能有效的解决局部最优…

    2022年7月12日
    15
  • bootstrap table表格分页样式问题[通俗易懂]

    bootstrap table表格分页样式问题[通俗易懂]bootstraptable表格分页样式问题今天项目里用到bootstrap做列表,数据展示没问题但是分页样式一直出不来,找了半天发现是因为没有引入css文件的问题&amp;amp;lt;head&amp;amp;gt;&amp;amp;lt;metacharset=&amp;quot;UTF-8&amp;quot;&amp;amp;gt;&amp;amp;lt;title&amp;amp;gt;Titl

    2022年7月17日
    20
  • DSSM & Multi-view DSSM TensorFlow实现

    DSSM & Multi-view DSSM TensorFlow实现LearningDeepStructuredSemanticModelsforWebSearchusingClickthroughData以及其后续文章AMulti-ViewDeepLearningApproachforCrossDomainUserModelinginRecommendationSystems的实现Demo。1.数据D

    2025年8月19日
    3
  • xml转Excel的软件_excel合并工具哪个好

    xml转Excel的软件_excel合并工具哪个好在线Excel转XML工具在线Excel转XML工具ExcelToXMLConverter可帮助你在线将excel文件转换为XML。ExcelToXMLConverter可帮助你在线将excel文件转换为XML。ExcelToXMLConverter可帮助你在线将excel文件转换为XML。https://toolgg.com/excel-to-xml.html…

    2022年8月22日
    5
  • 记录ci框架中定时任务的执行[通俗易懂]

    记录ci框架中定时任务的执行

    2022年2月10日
    44
  • mina框架是什么意思(个人年度总结框架)

    参考:http://xinsync.xju.edu.cn/index.php/archives/category/prglang/java/mina简单介绍:MINA框架是对java的NIO包的一个封装,简化了NIO程序开发的难度,封装了很多底层的细节,然开发者把精力集中到业务逻辑上来,最近做了一个相关的项目,为了备忘对MINA做一个总结。下面这个start方法用来初始化MINA:priv…

    2022年4月16日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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