其他分享
首页 > 其他分享> > 守护线程和定时器

守护线程和定时器

作者:互联网

声明

版权声明:本文部分内容参考自CSDN博主「一个快乐的野指针~」的原创文章,仅用作个人学习,特此声明
原文链接: https://blog.csdn.net/qq_44715943/article/details/116714584

守护线程

1、java语言中线程分为两大类:

守护线程中具有代表性的:垃圾回收线程


2、线程特点

一般守护线程是一个死循环所有的用户线程只要结束,守护线程自动结束

需要注意的是:主线程main方法是一个用户线程

每天00:00的时候系统数据自动备份。
这个需要使用到定时器,并且我们可以将定时器设置为守护线程。
一直在后台运行,每到00:00的时候就备份一次。如果所有的用户线程都结束了,守护线程自动退出,不再进行数据备份。


3、设置方法

方法名 作用
void setDaemon(boolean on) on为true表示把线程设置为守护线程

eg.

/**
 * 测试将线程设置为守护线程的方法
 * void setDaemon(boolean on)
 * on为true表示设置为守护线程
 */
public class SetTest {
    public static void main(String[] args) {
        Thread t = new BakDataThread();
        t.setName("备份数据的线程");

        // 启动线程之前,将线程设置为守护线程
        t.setDaemon(true);

        t.start();

        // 主线程:主线程是用户线程
        for(int i = 0; i < 3; i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class BakDataThread extends Thread {
    public void run(){
        int i = 0;
        // 即使是死循环,但由于该线程是守护者,当用户线程结束,守护线程自动终止。
        while(true){
            System.out.println(Thread.currentThread().getName() + "--->" + (++i));//先加1后输出
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


需要注意的是:


定时器

1、定时器作用:

间隔特定的时间,执行特定的程序。

eg.
每周要进行银行账户的总账操作。
每天要进行数据的备份操作。


在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的,在java中可以采用多种方式实现:

  1. 可以使用sleep方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务。这种方式是最原始的定时器。
  2. 在java的类库中已经写好了一个定时器:java.util.Timer,可以直接拿来用。不过,这种方式在目前的开发中也很少用,因为现在有很多高级框架都是支持定时任务的。

在实际的开发中,目前使用较多的是Spring框架中提供的SpringTask框架,这个框架只要进行简单的配置,就可以完成定时器的任务。


2、构造方法和方法

构造方法名 备注
Timer() 创建定时器
Timer(boolean isDaemon) isDaemon为true则为守护线程定时器
Timer(String name) 创建一个定时器,其线程名字为name
Timer(String name, boolean isDaemon) true则为守护线程name的定时器
方法名 作用
void schedule(TimerTask task, Date firstTime, long period) 安排指定的任务在指定的时间开始进行重复的固定延迟执行
void cancel() 终止定时器

3、eg.使用定时器实现日志备份

正常方式:

/**
 * 使用定时器实现日志备份
 * 用正常方式
 */
class TimerTest01{
    public static void main(String[] args) {
        Timer timer = new Timer();
//        Timer timer = new Timer(true);//守护线程
        String firstTimeStr = "2022-04-20 09:42:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date firstTime = sdf.parse(firstTimeStr);
            timer.schedule(new MyTimerTask(), firstTime, 1000 * 5);//每5s执行一次
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

class MyTimerTask extends TimerTask {
    @Override
    public void run() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = sdf.format(d);
        System.out.println(time + ":备份日志一次!");
    }
}
/**
 * 使用定时器实现日志备份
 * 用正常方式
 */
class TimerTest01{
    public static void main(String[] args) {
        Timer timer = new Timer();
//        Timer timer = new Timer(true);//守护线程
        String firstTimeStr = "2022-04-20 09:42:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date firstTime = sdf.parse(firstTimeStr);
            timer.schedule(new MyTimerTask(), firstTime, 1000 * 5);//每5s执行一次
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

class MyTimerTask extends TimerTask {
    @Override
    public void run() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = sdf.format(d);
        System.out.println(time + ":备份日志一次!");
    }
}

结果分析:



设定为到了九点四十二分才开始备份,很明显此时才九点四十一分,还没到时间,"待机"

如上图所示,时间一到,开始进行日志的备份工作


匿名内部类方式:

/**
 * 使用定时器实现日志备份
 * 用匿名内部类方式
 */
class TimerTest02{
    public static void main(String[] args) {
        Timer timer = new Timer();
        String firstTimeStr = "2022-04-20 9:42:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date firstTime = sdf.parse(firstTimeStr);
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    Date d = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String time = sdf.format(d);
                    System.out.println(time + ":备份日志一次!");
                }
            }, firstTime, 1000 * 5);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 使用定时器实现日志备份
 * 用匿名内部类方式
 */
class TimerTest02{
    public static void main(String[] args) {
        Timer timer = new Timer();
        String firstTimeStr = "2022-04-20 9:42:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date firstTime = sdf.parse(firstTimeStr);
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    Date d = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String time = sdf.format(d);
                    System.out.println(time + ":备份日志一次!");
                }
            }, firstTime, 1000 * 5);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

4、分析一下代码,加深理解

void schedule(TimerTask task, Date firstTime, long period)

首先,要调用schedule方法达到在指定时间Date firstTime每延迟long period执行一次TimerTask task工作的目的

我的目的是在2022-04-20 9:42:00开始,每隔5s钟,执行一次线程的run方法

  1. 首先要指定需要完成的任务task(可用匿名内部类实现)
class MyTimerTask extends TimerTask {
    @Override
    public void run() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = sdf.format(d);
        System.out.println(time + ":备份日志一次!");
    }
}
  1. 指定开始时间

步骤:

String firstTimeStr = "2022-04-20 9:42:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
timer.schedule(new MyTimerTask(), firstTime, 1000 * 5);//firstTime就是上边解析生成的Date
  1. 指定延迟时间为5s(1000*5ms)

顺便复习一下上边用到的SimpleDateFormat类的构造方法和方法

构造方法:

构造方法名 简介
SimpleDateFormat() 用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat
SimpleDateFormatg(String pattern) 用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat
SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols) 用给定的模式和日期符号构造 SimpleDateFormat
SimpleDateFormat(String pattern, Locale locale) 用给定的模式和给定语言环境的默认日期格式符号构造 SimpleDateFormat

方法:

方法名 简介
format(Date date, StringBuffer toAppendTo, FieldPosition pos) 将给定的 Date 格式化为日期/时间字符串,并将结果添加到给定的 StringBuffer
parse(String text, ParsePosition pos) 解析字符串的文本,生成 Date

标签:定时器,String,SimpleDateFormat,sdf,线程,Date,new,守护
来源: https://www.cnblogs.com/xypersonal/p/16169083.html