当前位置:首页 > Java技术 > Java多线程/并发03、实现定时任务的3种方法

Java多线程/并发03、实现定时任务的3种方法

2022年08月05日 10:08:46Java技术6

所谓定时任务有两个核心要素:
1、任务开始时间:可以指定任务在将来某个时间点运行,或者指定任务从现在开始延迟一个时间段运行
2、任务执行周期:可以指定该任务每间隔多久执行一次

Java实现定时任务有三种方法:

一、利用Thread及Sleep实现,通过while循环让其不停运行

public class TimerTaskDemo {
     
    public static void main(String[] args) {
        Runnable runable=new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程执行任务,当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            }
        };
        try {
            System.out.println("主线程启动子线程时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            scheduleThread(5L,3,runable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /***
     * 
     * @param duration 指定什么时间后运行 单位:秒
     * @param timeInterval 每次运行间隔时间 单位:秒
     * @param runnable 待运行的Runable对象
     * @throws InterruptedException
     */
    static void scheduleThread(Long duration,Integer timeInterval,Runnable runnable) throws InterruptedException{
        /*阻塞等待*/
        TimeUnit.SECONDS.sleep(duration);
        //Thread.sleep(duration*1000);
        final Runnable interiorRun=runnable;
        final Integer interiorTimeInterval=timeInterval;
        /*运行*/
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    /*执行方法*/
                    interiorRun.run();
                    try {
                        /*任务执行间隔*/
                        TimeUnit.SECONDS.sleep(interiorTimeInterval);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

二、利用Timer和TimerTask

先说下两者关联和区别:
1、Timer是调度者,可以安排任务执行计划,包括:任务时间、执行频率,也可停止任务。
2、TimerTask是任务。Timer类可以调度TimerTask任务,TimerTask则通过在run()方法里实现具体任务。TimerTask也可停止自身任务。
3、一个Timer可以调度多个TimerTask。
4、Timer是单线程的:Timer构造函数调用时会创建了一个新线程,所有TimerTask都是依靠这个新的线程执行。默认线程名:Timer-0

模拟一个进度条:

public class TimerTaskDemo {
     
    public static void main(String[] args) {
        Timer timer = new Timer();   
        MyTimerTask mytask=new MyTimerTask();
            timer.schedule(mytask, 0, 300);
         try {
            TimeUnit.SECONDS.sleep(10);
            /*10秒后停止任务*/
            mytask.cancel();//停止运行指定的TimerTask
            //timer.cancel();//停止运行timer上所有TimerTask
            System.out.print("100%");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    static class MyTimerTask extends java.util.TimerTask {
     
        public void run() {
            System.out.print(">");
        }
    }
}

三、ScheduledExecutorService

Java SE 5后在JUC中提供了一个工具类:ScheduledExecutorService,这是最理想的定时任务实现方式。
相比于上两种方法,它有以下好处:
1、相比于Timer的单线程,它是通过线程池的方式来执行任务的。
2、可以很灵活的去设定第一次执行任务delay时间。
3、方法中提供TimeUnit,可设定时间单位。

public class TimerTaskDemo {
     
    public static void main(String[] args) {
        ScheduledExecutorService ses=Executors.newScheduledThreadPool(2);
        ses.scheduleAtFixedRate(new MyTimerTask(), 2, 1, TimeUnit.SECONDS);
        ses.scheduleAtFixedRate(new MyTimerTask(), 1, 1, TimeUnit.SECONDS);
        try {
            TimeUnit.SECONDS.sleep(10);
            /*10秒后停止任务*/
            ses.shutdown();//停止运行线程池上的所有runable。
            System.out.print("--运行10秒停止--");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /*TimerTask实现Runable接口*/
    static class MyTimerTask extends java.util.TimerTask {
     
        public void run() {
            System.out.println(Thread.currentThread().getName()+":"+ Calendar.getInstance().get(Calendar.SECOND));
        }
    }
}

输出结果,可以看到开启了两个线程运行任务。(pool-1-thread-1及pool-1-thread-2)

作者:唐大麦
来源链接:https://blog.csdn.net/soonfly/article/details/70917204

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/17529.html

分享给朋友:

“Java多线程/并发03、实现定时任务的3种方法” 的相关文章

Java实现Email发送

一、前言最近将项目的登录密码从图形验证码改为了短信验证码,同时也将忘记密码时长度进行了修改,在修改时,想到了之前在一些国外的网站上,使用过邮箱接收验证码的情况,故想到何妨不自己尝试整合一下Java程序发送邮件信息呢,所以动手整合了Email的发送实例。二、Email发送协议想要在互联网上提供电子邮件...

Java中四种访问修饰符的区别

在java中共有4种访问级别,按访问权限由高到低为:public(公有的)、protected(受保护的)、友好的(没有任何访问权限关键字修饰)和private(私有的)。 类型 类内部 同一个包其...

全面了解 Java 原子变量类

📦 本文以及示例源码已归档在 javacore 一、原子变量类简介 为何需要原子变量类 保证线程安全是 Java 并发编程必须要解决的重要问题。Java 从原子性、可见性、有序性这三大特性入手,确保多线程的数据一致性。 确保线程安全最...

Java日志框架那些事儿

Java日志框架那些事儿

在项目开发过程中,我们可以通过 debug 查找问题。而在线上环境我们查找问题只能通过打印日志的方式查找问题。因此对于一个项目而言,日志记录是一个非常重要的问题。因此,如何选择一个合适的日志记录框架也非常重要。在Java开发中,常用的日志记录框架有JDKLog、Log4J、LogBack、SLF4J...

Java实现素数的判断

素数的定义只能被1和它本身整除,不包括1 例 2.3.5.7.11.13 实现代码 Scanner in=new Scanner(System.in); int n ; n=in.nextInt(); for(int n1=2;n1&l...

枚举法 之Java实现凑硬币

问题? 如何利用1元五元十元凑硬币 Scanner in=new Scanner(System.in); int amout ; amout=in.nextInt(); for(int one =0;one<=amout;one+...

二分法(折半查找)的运用之java实现猜数字游戏

让计算机输入一个数 然后用户进行猜数游戏 一般而言,七次会猜对,如果猜不对,那么就是你的方法不对 在这儿涉及到的一个算法就是二分法 ***二分法查找,***也称为折半法,是一种在有序数组中查找特定元素的搜索算法。二分法查找的思路如下: (1)首先,从数组...

Java打印车票主要学习Java的比较语句

直接上代码 public static void main(String[] args) { // TODO Auto-generated method stub //初始化 Scanner in=new Scanner(S...

java中将英尺换算为身高

java中将英尺换算为身高

直接上代码 如图所示便是身高的换算,你学到了吗?、 int foot; double inch; Scanner in=new Scanner(System.in); foot=in.nextInt(); inch=in.nextDouble...

Java对象的大小

基本数据的类型的大小是固定的,这里就不多说了。对于非基本类型的Java对象,其大小就值得商榷。 在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任何属性的对象的大小。看 下面语句: Object ob = new Ob...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。