我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java任务定时执行器案例的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java任务定时执行器案例的实现

⭐️前面的话⭐️

本篇文章将介绍Java多线程案例,定时器,定时器就像闹钟一样,等到了指定的时间,闹钟就会发出响声来提醒您,而定时器会执行指定的任务。

?1.定时器概述

?1.1认识定时器

java中的定时器,也可以叫做任务定时执行器,顾名思义,就是等到了指定的时间,就去做指定的事情,就像你每周六或周日都要去力扣参加周赛一样。

所以你如果想要使用定时器,你需要交代时间和对应的任务才行,java标准也提供了带有定时器功能的类Timer

?1.2Timer类的使用

在java1.8中,Timer给出了四个构造方法,这些构造方法可以去指定线程的名字和是否将定时器内部的线程指定为守护线程。

好了,又出现了一个新概念,这个守护线程是什么鬼?
其实在java中有两种线程,一种是用户线程,另外一种是守护线程。用户线程就是普通的线程,守护线程顾名思义就是守护用户线程的线程,可以说就是用户线程的保姆,守护线程与JVM“共存亡”, 只要存在一个用户线程,程序中所有的守护线程都不会停止工作,直到最后一个用户线程执行完毕,守护线程才会停止工作。守护线程最典型的应用就是 GC (垃圾回收器),它就是一个非常称职的守护者。

?构造方法:

序号构造方法说明
1public Timer()无参数构造方法,默认定时器关联的线程不是守护线程,线程名字也是默认值
2public Timer(boolean isDaemon)指定定时器中关联的线程是否为守护线程,如果是,参数为true
3public Timer(String name)指定定时器关联线程名称,线程类型默认为非守护线程
4public Timer(String name, boolean isDaemon)指定定时器关联线程名和线程类型

Timer类构造时内部也会创建线程,如果不指定,定时器对象内部的线程(为了简化,就称为关联线程吧)的类型是用户线程,而不是守护线程。

?核心方法:

序号方法说明
1public void schedule(TimerTask task, long delay)指定任务,延迟多久执行该任务
2public void schedule(TimerTask task, Date time)指定任务,指定任务的执行时间
3public void schedule(TimerTask task, long delay, long period)连续执行指定任务,延迟时间,连续执行任务的时间间隔,毫秒为单位
4public void schedule(TimerTask task, Date firstTime, long period)连续执行指定任务,第一次任务的执行时间,连续执行任务的时间间隔
5public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)与方法4作用相同
6public void scheduleAtFixedRate(TimerTask task, long delay, long period)与方法3作用相同
7public void cancel()终止定时器所有任务,终止执行的任务不受影响

?使用演示:

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue;

public class TimeProgram {
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行延后2s执行的任务!");
            }
        }, 2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行延后5s执行的任务!");
            }
        }, 5000);

        //每秒输出一个mian
        for (int i = 0; i < 5; i++) {
            System.out.println("main");
            Thread.sleep(1000);
        }
    }
}

?运行结果:

TimerTask类就是专门描述定时器任务的一个抽象类,它实现了Runnable接口。

public abstract class TimerTask implements Runnable    //jdk源码

下面我们简单实现一下定时器,我们就不用TimerTask了,我们直接使用Runnable,因为TimerTask实现了Runnable接口,所以后面测试我们自己所写的schedule方法时,也可以传入TimerTask类型的引用,既然是简单地实现,那就不实现连续执行的功能了。

?2.定时器的简单实现

首先,我们需要建造一个类,来描述定时器的任务,可以使用Runnable加上一个任务执行的时间戳就可以了。
?具体清单:
一个构造方法,用来指定任务和延迟执行时间。
两个获取方法,用来给外部对象获取该对象的任务和执行时间。
实现比较器,用于定时器任务对象的组织,毕竟,每次需要执行时间最早的任务,需要用到基于小根堆实现的优先队列,不,还需要考虑多线程的情况,还是使用优先级阻塞队列吧。

//我的任务
class MyTask implements Comparable<MyTask> {
    //接收具体任务
    private Runnable runnable;
    //执行时的时间戳
    private long time;

    //构造方法
    public MyTask(Runnable runnable, int delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    //执行任务
    public void run() {
        this.runnable.run();
    }
    //获取执行时间
    public long getTime() {
        return this.time;
    }

    //实现comparable接口,方便创建优先级阻塞队列
    @Override
    public int compareTo(MyTask o) {
        return (int) (this.time - o.time);
    }
}

接下来就要实现定时器类了,首先我们需要一个数据结构来组织定时器任务,并且每次都能将时间最早的任务找到并执行,那么这个数据结构非小根堆莫属了,也就是优先级队列,注意对自定义类使用优先级队列时,一定要实现比较器。

    //每次执行任务时,需要优先执行时间在前的任务,即每次执行任务要选择时间戳最小的任务,在多线程情况中优先级阻塞队列是最佳选择
    private static final PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue<>();

然后,需要一个方法将任务安排在优先级阻塞队列中,最后在构造定时器对象的时候从优先级阻塞队列中取任务并在指定的时间执行。

按照上图的逻辑,我们自己实现的定时器类需要有一个线程专门去执行任务,执行任务过程中可能会遇到执行时间还没有到的情况,那么线程必须得等待,线程等待的方法有两种,一种是wait另一种是sleep,这个案例我们推荐前者,因为sleep方法不能中途唤醒,这个案例是有可能需要中途唤醒的,那就是有新任务插入时,需要重新去优先级阻塞队列拿任务重复上述操作,这个唤醒操作可以使用notify方法实现,所以需要用到wait/notify组合拳,既然需要使用wait/notify那么就得有锁,所以我们可以使用一个专门的锁对象来加锁。

?实现代码:

//我的定时类 用来管理任务
class MyTimer {
    //专门对锁对象
    private final Object locker = new Object();
    //每次执行任务时,需要优先执行时间在前的任务,即每次执行任务要选择时间戳最小的任务,在多线程情况中优先级阻塞队列是最佳选择
    private static final PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue<>();

    //安排任务
    public void schedule(Runnable runnable, int delay) {
        //将任务放入小根堆中
        MyTask task = new MyTask(runnable, delay);
        priorityBlockingQueue.put(task);
        //每次当新任务加载到阻塞队列时,需要中途唤醒线程,因为新进来的任务可能是最早需要执行的
        synchronized (locker) {
            locker.notify();
        }
    }
    public MyTimer() {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    //加载任务,确定执行时机
                    MyTask myTask = priorityBlockingQueue.take();
                    long curTime = System.currentTimeMillis();
                    //时间未到,将任务放回
                    if (curTime < myTask.getTime()) {
                        synchronized (locker) {
                            priorityBlockingQueue.put(myTask);
                            //放回任务后,不能立即就再次取该任务加载,需要设置一个再次加载的等待时间,建议使用wait带参数的方法
                            //因为wait方法可以使用notify进行中途唤醒,而sleep不能中途唤醒
                            int delay = (int)(myTask.getTime() - curTime);
                            locker.wait(delay);
                        }
                    } else {
                        System.out.println(Thread.currentThread().getName() + "线程收到任务,正在执行中!");
                        myTask.run();
                        System.out.println(Thread.currentThread().getName() + "线程执行任务完毕,正在等待新任务!");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //不要忘了启动线程
        thread.start();
    }
}

?上面是我们实现定时器的代码,我们来测试一下:

import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue;

public class TimeProgram {
    public static void main(String[] args) throws InterruptedException {
        MyTimer timer = new MyTimer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行延后2s执行的任务!");
            }
        }, 2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行延后5s执行的任务!");
            }
        }, 5000);

        //每秒输出一个mian
        for (int i = 0; i < 5; i++) {
            System.out.println("main");
            Thread.sleep(1000);
        }
    }
}

?执行结果:

好了,任务定时执行器你学会了吗?

到此这篇关于Java任务定时执行器案例的实现的文章就介绍到这了,更多相关Java任务定时执行器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java任务定时执行器案例的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java web如何实现每天定时执行任务

小编给大家分享一下java web如何实现每天定时执行任务,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!第一步:package com.eh.util;import java.util.Calendar;import ja
2023-05-30

java如何定时执行任务

java如何定时执行一个方法java实现定时功能有多种方式,下面介绍3种:1、创建一个线程.import java.util.Date;public class ThreadTest { public static void main(String[]
java如何定时执行任务
2022-04-07

android定时执行任务怎么实现

Android定时执行任务可以通过以下几种方式实现:1. 使用Handler和Timer:创建一个Handler对象,在Handler的回调方法中执行定时任务,并使用Timer对象进行定时调度。```javaHandler handler
2023-09-21

php怎么实现定时执行任务

在PHP中,可以使用以下几种方法来实现定时执行任务:1. 使用cron表达式:cron表达式是一种常用的定时任务调度语法,可以在操作系统的定时任务管理工具(如Linux的cron)中设置定时执行PHP脚本。例如,可以在终端中使用`cront
2023-08-12

Linux中如何实现crontab定时执行任务

小编给大家分享一下Linux中如何实现crontab定时执行任务,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!基本格式 : *  *  *  *  *  comm
2023-06-13

Laravel每秒执行定时任务怎么实现

这篇文章主要介绍“Laravel每秒执行定时任务怎么实现”,在日常操作中,相信很多人在Laravel每秒执行定时任务怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Laravel每秒执行定时任务怎么实现
2023-07-04

如何实现 Java Crontab 定时任务监控方案?(java crontab定时任务监控方案)

在Java开发中,定时任务是一项非常常见且重要的功能,而Crontab是一种常用的定时任务调度工具。本文将详细介绍JavaCrontab定时任务监控方案,帮助开发者更好地理解和应用这一技术。一、Crontab简介
如何实现 Java Crontab 定时任务监控方案?(java crontab定时任务监控方案)
Java2024-12-17

Java实现定时任务的示例代码

这篇文章主要为大家详细介绍了Java实现定时任务的相关知识,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2022-11-21

django定期执行任务(实例讲解)

要在django项目中定期执行任务,比如每天一定的时间点抓取数据,刷新数据库等,可以参考stackoverflow的方法,先编写一个manage.py命令,然后使用crontab来定时执行这个命令。 定制manage.py命令 app可以使
2022-06-04

Java定时任务如何防止重复执行?(java定时任务防止重复执行的方法是什么)

在Java开发中,定时任务是一种常见的需求,用于在特定时间执行某些操作。然而,在处理定时任务时,我们经常会遇到重复执行的问题,这可能会导致不必要的资源消耗和数据不一致性。本文将介绍一些在Java中防止定时任务重复执行的方法。一、使用数据库记录任务执行状态
Java定时任务如何防止重复执行?(java定时任务防止重复执行的方法是什么)
Java2024-12-18

php ignore_user_abort()实现计划(定时执行)任务功能

要实现计划任务功能,可以使用ignore_user_abort()函数来忽略用户中断,并且在后台继续执行脚本。以下是一个示例,展示了如何使用ignore_user_abort()函数来实现计划任务功能:```php// 设置脚本不会在用户断
2023-10-11

springboot执行延时任务之DelayQueue实例

这篇文章主要介绍了springboot执行延时任务之DelayQueue实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录