Java多线程案例实战之定时器的实现

 更新时间:2024年01月23日 10:41:27   作者:兜里有颗棉花糖  
在Java中可以使用多线程和定时器来实现定时任务,下面这篇文章主要给大家介绍了关于Java多线程案例之定时器实现的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、Timer定时器

Java中,Timer类是用于计划和执行重复任务的类(Java标准库中确实提供了java.util.Timer类)。它可以在指定的时间间隔内重复执行一个任务,或者在指定时间点执行任务。

二、Timer定时器的设计

选择java.util包中的Timer类:

在这里插入图片描述

使用了Timer类的schedule()方法来安排一个任务在延迟3000毫秒后执行。在TimerTask的run()方法中,我们编写需要执行的具体任务逻辑。我们现在来了解一下TimerTask()这个抽象类(如下图):该类是一个抽象类,并且继承了Runnable方法。创建了一个匿名内部类并实现了run()方法。这个匿名内部类可以被认为是继承了TimerTask抽象类,并提供了具体的实现代码。

在这里插入图片描述

调用timer.schedule()方法注册的任务,会由Timer内部的线程池去执行,而不是由调用schedule()方法的线程直接执行run()方法。
Timer类内部创建了一个线程池,用于执行注册的定时任务。当调用schedule()方法后,Timer会将传入的TimerTask对象添加到线程池中进行调度。

下面是一个简单的定时器程序,可以运行试试看:

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

public class Demo22 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello world!!!");
            }
        },3000);
        System.out.println("程序开始执行喽!!!");
    }
}

运行结果如下:

在这里插入图片描述

可以看到程序并没有结束进程,原因如下:Timer内部有自己的线程,为了保证随时处理新安排的任务,此线程会一直持续的执行,即此线程影响了阻止来整个进程的结束。

定时器是支持多个任务同时执行的,请看:

在这里插入图片描述

在这里插入图片描述

三、定时器的实现

代码实现如下:

import java.util.Comparator;
import java.util.PriorityQueue;

class MyTimerTask implements Comparable<MyTimerTask> {
    private long time; // 表示任务什么时候开始执行
    private Runnable runnable; // 表示具体任务是啥

    public MyTimerTask(Runnable runnable,long delay) {
        // delay是一个相对的时间差
        time = System.currentTimeMillis() + delay;// 这里计算出任务执行的具体时间
        this.runnable = runnable;
    }

    public long getTime() {
        return time;
    }

    public Runnable getRunnable() {
        return runnable;
    }


    @Override
    public int compareTo(MyTimerTask o) {
        // 时间最少的元素放在队首,即时间越少优先级越高
        return (int)(this.time - o.time); // time是long类型
    }
}

// 这是定时器类的本体
class MyTimer {
    // 使用优先级队列来保存上面的N个任务
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    // locker是用来加锁的对象
    private Object locker = new Object();

    // 定时器的核心方法,即把要执行的任务添加到队列中
    public void schedule(Runnable runnable,long delay) {
        synchronized (locker) {
            MyTimerTask task = new MyTimerTask(runnable,delay);
            queue.offer(task);
            // 每次来新的任务之后都会唤醒一下扫描线程,此时扫描线程就可以根据最新的任务情况来重新规划等待时间
            locker.notify();
        }
    }
    // MyTimer类中还需要一个扫描线程,一方面要负责检查队首元素是否是此时应该被执行的。
    // 另一方面,当任务到点开始执行之后,需要调用Runnable中的run方法来完成任务
    public MyTimer() {
        // 扫描线程
        Thread t = new Thread(() -> {
            while(true) {
                try {
                    synchronized(locker) {
                        while(queue.isEmpty()) {
                            // 队列为空时,此时不应该取这里的元素
                            locker.wait();
                        }
                        MyTimerTask task = queue.peek();
                        long curTime = System.currentTimeMillis();
                        if(curTime > task.getTime()) {
                            // 如果当前时间晚于任务的执行时间,就意味着我们要执行这个任务了
                            queue.poll();
                            task.getRunnable().run(); // 至此就可以执行该任务了
                        } else {
                            // 如果当前时间早于任务的执行时间,诶呀太早了,让这个线程(休眠)休息一会一会吧!!!
                            // Thread.sleep(task.getTime() - curTime);
                            locker.wait(task.getTime() - curTime);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }

}

public class Demo23 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world! 3");
            }
        },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world! 2");
            }
        },2000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world! 1");
            }
        },1000);
        System.out.println("程序开始执行!!!");
    }
}

运行结果如下:

在这里插入图片描述

四、总结

Timer类是Java中的定时工具类,它可以帮助我们实现在指定时间执行指定任务的功能。Timer类提供了一个方法即schedule方法,我们可以通过schedule方法来注册一个任务并指定执行该任务的时间,当执行时间到的时候,Timer类内部的线程就会负责调用执行注册的任务。

另外我们可以通过优先级队列的方式来实现类似于Timer类这样的定时器。

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

相关文章

  • Log4j2 重大漏洞编译好的log4j-2.15.0.jar包下载(替换过程)

    Log4j2 重大漏洞编译好的log4j-2.15.0.jar包下载(替换过程)

    Apache 开源项目 Log4j 的远程代码执行漏洞细节被公开,由于 Log4j 的广泛使用,该漏洞一旦被攻击者利用会造成严重危害,下面小编给大家带来了Log4j2 重大漏洞编译好的log4j-2.15.0.jar包下载,感兴趣的朋友一起看看吧
    2021-12-12
  • 线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决记录

    线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决记录

    系统相关使用人员反馈系统故障,这篇文章主要介绍了线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决的记录,有需要的朋友可以借鉴参考下
    2022-03-03
  • java中如何获取时间戳的方法实例

    java中如何获取时间戳的方法实例

    时间戳通常是一个字符序列,唯一地标识某一刻的时间,所以下面这篇文章主要给大家介绍了关于java中如何获取时间戳的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-11-11
  • Java女装商城系统的实现流程

    Java女装商城系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SSM+jsp+mysql+maven实现一个女装商城系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • java访问者模式的静态动态及伪动态分派彻底理解

    java访问者模式的静态动态及伪动态分派彻底理解

    这篇文章主要为大家介绍了java访问者模式的静态动态及伪动态分派彻底理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • MDC在多线程中的使用方式

    MDC在多线程中的使用方式

    这篇文章主要介绍了MDC在多线程中的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java创建和填充PDF表单域方法

    Java创建和填充PDF表单域方法

    在本篇文章中小编给大家分享了关于Java创建和填充PDF表单域方法和步骤,有需要的朋友们学习下。
    2019-01-01
  • springboot+log4j.yml配置日志文件的方法

    springboot+log4j.yml配置日志文件的方法

    这篇文章主要介绍了springboot+log4j.yml配置日志文件的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Java判断两个日期相差天数的方法

    Java判断两个日期相差天数的方法

    这篇文章主要介绍了Java判断两个日期相差天数的方法,以实例形式对比分析了java进行日期换算及对比的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Java实现在PPT中创建SmartArt图形的示例代码

    Java实现在PPT中创建SmartArt图形的示例代码

    SmartArt其实就是一个文字的可视化工具,用户可在PowerPoint,Word,Excel中使用该特性创建各种图形图表。本文就将为您介绍如何通过Java应用程序在PPT中创建SmartArt图形,需要的可以参考一下
    2023-04-04

最新评论