5.定时器Timer


本章着重掌握如下2个知识点:

  • 如何实现指定时间执行任务
  • 如何实现按指定周期执行任务

定时器Timer的使用
介绍:在JDK库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。Timer类的主要作用就设置计划任务,但封装任务的类却是TimerTask类。执行任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类。

方法schedule(TimerTask task, Date time):
说明:该方法的作用是在指定的日期执行一次某一任务
看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }

    public static void main(String[] args){
        try{
            MyTask task = new MyTask();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2017-04-28 17:48:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间: " + dateRef.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            timer.schedule(task, dateRef);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}

结果:
这里写图片描述

分析:1.从结果可以看到,任务虽然执行完了,但进程还未销毁,呈红色状态,为什么会出现这样的情况呢?查看Timer的构造方法可以得知,创建一个Timer就是启动了一个新的线程,这个新启动的线程并不是守护线程,它一直在运行。如果想让Timer成为守护线程,该怎么做呢?new Timer(true)就可以了。2.根据所提供的datetime,如果大于当前时间,则到响应时间执行,若小于等于当前时间,则任务立即执行。


多个TimerTask任务
**介绍:**Timer中允许有多个TimerTask任务。

看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    static public class MyTask1 extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }

    static public class MyTask2 extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }

    public static void main(String[] args){
        try{
            MyTask1 task1 = new MyTask1();
            MyTask2 task2 = new MyTask2();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString1 = "2017-04-28 18:50:00";
            String dateString2 = "2017-04-28 17:51:00";
            Date dateRef1 = sdf1.parse(dateString1);
            Date dateRef2 = sdf1.parse(dateString2);
            System.out.println("字符串1时间: " + dateRef1.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            System.out.println("字符串2时间: " + dateRef2.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            timer.schedule(task1, dateRef1);
            timer.schedule(task2, dateRef2);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}



结果:
这里写图片描述

总结:TimerTask是以队列的方式一个一个被顺序执行的,所以执行的时间有可能和预期的时间不一致,因为前面的任务有可能消耗的时间较长,则后面的任务运行的时间也会被延迟。


方法shcedule(TimerTask task, Date firstTime, long period)
说明:该方法的作用是指在指定的日期后,按指定的间隔周期性地无限循环地执行某一任务。
看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }


    public static void main(String[] args){
        try{
            MyTask task = new MyTask();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2017-04-28 18:57:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串1时间: " + dateRef.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            timer.schedule(task, dateRef, 4000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}



结果:
这里写图片描述
总结:从运行结果来看,每隔4秒运行一次TimerTask任务,并且是无限期地重复执行。

TimerTask类的cancel()方法
**说明:**TimerTask类中的cancel()方法的作用是将自身从任务队列中清除。

看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    static public class MyTaskA extends TimerTask{
        @Override
        public void run(){
            System.out.println("A运行了!时间为:" + new Date());
            this.cancel();
        }
    }

    static public class MyTaskB extends TimerTask{
        @Override
        public void run(){
            System.out.println("B运行了!时间为:" + new Date());
        }
    }


    public static void main(String[] args){
        try{
            MyTaskA taskA = new MyTaskA();
            MyTaskB taskB = new MyTaskB();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2017-04-28 18:57:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间: " + dateRef.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            timer.schedule(taskA, dateRef, 4000);
            timer.schedule(taskB, dateRef, 4000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}



结果:
这里写图片描述
总结:从运行结果来看,TimerTask类的cancel()方法是将自身从任务队列中被移除,其他任务不受影响。

Timer类的cancel()方法
说明:和TimerTask类中的cancel()方法清除自身不同,Timer类中的cancel()方法的作用是将任务队列中的全部任务清空。

看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    static public class MyTaskA extends TimerTask{
        @Override
        public void run(){
            System.out.println("A运行了!时间为:" + new Date());
            timer.cancel();
        }
    }

    static public class MyTaskB extends TimerTask{
        @Override
        public void run(){
            System.out.println("B运行了!时间为:" + new Date());
        }
    }


    public static void main(String[] args){
        try{
            MyTaskA taskA = new MyTaskA();
            MyTaskB taskB = new MyTaskB();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2017-04-28 18:57:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间: " + dateRef.toLocaleString() + " 当前时间: " + new Date().toLocaleString());
            timer.schedule(taskA, dateRef, 4000);
            timer.schedule(taskB, dateRef, 4000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}



结果:
这里写图片描述
总结:从运行结果来看,全部任务都被清除,并且进程被销毁,按钮又红色变成灰色。

Timer类的cancel()方法的注意事项
**说明:**Timer类中的cancel()方法有时并不一定会停止执行计划任务,而是正常执行。

看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by yongshan_ning on 2017/4/28.
 */
public class Run1 {
    static int i = 0;
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            System.out.println("A运行了!时间为:" + i);
        }
    }

    public static void main(String[] args){
        while (true) {
            try {
                i++;
                Timer timer = new Timer();
                MyTask task = new MyTask();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String dateString = "2017-04-28 18:57:00";
                Date dateRef = sdf.parse(dateString);
                timer.schedule(task, dateRef);
                timer.cancel();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }
}



结果:
这里写图片描述
总结:因为Timer类中的cancel()方法有时并没有争抢到queue锁,所以TimerTask类中的任务继续正常执行了。

方法schedule(TimerTask task, long delay)
说明:该方法的作用是以执行shcedule(TimerTask task, long delay)方法当前的时间为参考时间,在此时间基础上延迟指定的毫秒数后执行一次TimerTask任务。

看个例子:

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

public class Run1 {
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }

    public static void main(String[] args) {
            Timer timer = new Timer();
            MyTask task = new MyTask();
            System.out.println("当前时间: "  + new Date().toLocaleString());
            timer.schedule(task, 7000);
    }

}



结果:
这里写图片描述
总结:从运行结果来看,任务task被延迟7秒执行。

方法schedule(TimerTask task, long delay, long period)
说明:该方法的作用是以执行shcedule(TimerTask task, long delay, long period)方法当前的时间为参考时间,在此时间基础上延迟指定的毫秒数,再以某一件间隔无限次数地执行某一任务。

看个例子:

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

public class Run1 {
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            System.out.println("运行了!时间为:" + new Date());
        }
    }

    public static void main(String[] args) {
            Timer timer = new Timer();
            MyTask task = new MyTask();
            System.out.println("当前时间: "  + new Date().toLocaleString());
            timer.schedule(task, 3000, 5000);
    }

}



结果:
这里写图片描述
总结:从运行结果来看,任务task被延迟3秒执行,并间隔5秒无限循环执行。

方法scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
说明:方法schedule和方法scheduleAtFixedRate都会按顺序执行,所以不要考虑非线程安全的情况。方法shcedule和scheduleAtFixedRate主要的区别只在于不延时的情况。

使用schedule方法:如果执行任务的时间没有被延时,那么下一次任务的执行事件参考的是上一次任务的”开始”时的时间来计算。

使用scheduleAtFixedRate方法:如果执行任务的时间没有被延时,那么下一次任务的执行事件参考的是上一次任务的”结束”时的时间来计算。

延时的情况则没有区别,也就是使用shcedule或scheduleAtFixedRate方法都是如果执行任务的时间被延时,那么下一次任务的执行事件参考的是上一次任务”结束”时的时间来计算。
看个例子:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Run1 {
    private static Timer timer = new Timer();
    private static int runCount = 0;
    static public class MyTask extends TimerTask{
        @Override
        public void run(){
            try {
                System.out.println("begin 运行了!时间为:" + new Date());
                Thread.sleep(1000);
                System.out.println("  end 运行了!时间为:" + new Date());
                runCount++;
                if(runCount == 5){
                    timer.cancel();
                }
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        try {
            MyTask task = new MyTask();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2017-04-28 19:39:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间"+dateRef.toLocaleString()+" 当前时间: " + new Date().toLocaleString());
            timer.scheduleAtFixedRate(task, dateRef, 3000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }

}



结果:
这里写图片描述
总结:从运行结果来看,如果执行任务的时间没有被延时,则下一次任务的执行事件以上一次任务的开始时间加上delay时间。反之,如果被延时,则下一次执行任务的时间是上一次任务结束的时间。schedule方法不具有追赶执行性,scheduleAtFixedRate方法具有追赶执行性。

基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时间。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件组件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值