守护线程和定时器
作者:互联网
声明
版权声明:本文部分内容参考自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();
}
}
}
}
需要注意的是:
- 主线程main属于用户线程
- 一般把守护线程设置为死循环
- 用户线程不结束,守护线程就一直执行下去,直到用户线程执行完毕,守护线程自动停止
定时器
1、定时器作用:
间隔特定的时间,执行特定的程序。
eg.
每周要进行银行账户的总账操作。
每天要进行数据的备份操作。
在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的,在java中可以采用多种方式实现:
- 可以使用sleep方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务。这种方式是最原始的定时器。
- 在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方法
- 首先要指定需要完成的任务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 + ":备份日志一次!");
}
}
- 指定开始时间
步骤:
- 创建时间字符串。需要注意的是创建的时间字符串格式一定要跟构造
SimpleDateFormat
所指定的格式保持一致!!!如下代码所示:
String firstTimeStr = "2022-04-20 9:42:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
用SimpleDateFormat类的parse方法解析字符串文本,生成Date
-
生成的Date拿来直接用
timer.schedule(new MyTimerTask(), firstTime, 1000 * 5);//firstTime就是上边解析生成的Date
- 指定延迟时间为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