Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器
每博一文案
正如村上春树所说:“当暴风雨过去,你不会记得自己是如何度过的,你甚至不确定,暴风雨是否真正结束了,
但你已不再是当初走进暴风雨的那个人了。这就是暴风雨的意义。”
一个人经历过挫折,才会更好的成长,经历这些才能珍惜所拥有的。
佛说:“无论你遇到谁,他都是对的人,无论发生什么事,那都是唯一会发生的事。”
有些人的出现,从一开始就不是为了大结局,而是为了给生活增加一段插曲。
只是为了经由那个人,让你更了解自己,所以遇到谁,有过怎样的故事,都是人生的宝贵财富。
比起抽刀断水的决绝,人更怕的是自我感动,明明付错心等错人,却还说着可以为爱一无所有。
明知道走错了路,回头就行,明知道爱错了人,放手就好。
但对于付出过真心的东西,总有不舍得立刻叫停,总觉得再坚持一下也许就会找到出路。
结局却往往是拖泥又带水,蹉跎一日复一日。
有这样一段话:“成长是一个人的朝圣路,没有一个人能够助另一个人成长,再多的左突右突和痛苦,我们都要像蝉一样,蜕一层皮,
然后把内心的痛苦和恐惧不安统统丢掉。”
人之相遇,已是不易,若能相知相伴,更是少之又少。并不是每一段爱都会开花结果。但可以肯定的是,每一份爱都曾化为
成长的力量,在无数的黑暗的夜里默默温暖着我们。
茫茫人海中的相遇,已然胜过所有的悲欢。或是痛苦,或是美好,都是一种经历,经历过就是收获,又何必在乎结局如何。
因此,不要害怕去爱,不要害怕被爱,希望你明白,爱错了人也不怕,因为凡是经历,皆为成长。
—————— 一禅心灵庙语
文章目录
- Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器
- 每博一文案
- 一. 线程的优先级
- 二. 线程的中断
- 三. 线程的分类
- 四. 线程的定时器
- 五. 总结:
- 六. 最后:
一. 线程的优先级
对于线程的优先级的使用 Thread 类中的 getPriority()
获取当前线程的优先级和 setPriority(int newPriority)
设置线程的优先级
需要注意的是:线程的优先级是在 [10~1] 之间的,其中 5 是默认线程的优先级 。
- MIN_PRIORITY = 1 线程的最小优先级
- NORM_PRIORITY = 5 线程的默认优先级
- MAX_PRIORITY = 10 线程的最大优先级
- 当所设置的线程优先级,不再 [10~1] 这个区间内报:
IllegalArgumentException
非法参数异常。
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
补充:
- 线程创建时继承父线程的优先级
- 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用,高优先级的线程也不是一定就比低的优先级线程先执行,只是先被执行的概率更高而已,注意是 概率不是绝对 。
如下
package blogs.blog4;
public class ThreadTest11 {
public static void main(String[] args) {
Thread t1 = new Thread(new MyThread11()); // 线程一
Thread t2 = new Thread(new MyThread11()); // 线程二
Thread t3 = new Thread(new MyThread11()); // 线程二
Thread t4 = new Thread(new MyThread11()); // 线程二
// 设置线程名
t1.setName("线程一");
t2.setName("线程二");
t3.setName("线程三");
t4.setName("线程三");
// 设置线程的优先级
t1.setPriority(Thread.MIN_PRIORITY); // 最小 1
t2.setPriority(Thread.NORM_PRIORITY); // 默认 5
t3.setPriority(Thread.MAX_PRIORITY); // 最大 10
t4.setPriority(6); // 设置为 6
// 创建新线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class MyThread11 implements Runnable {
@Override
public void run() { // Thread.currentThread().getPriority() 获取当前线程的优先级
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
二. 线程的中断
关于线程 interrupt()
大家可以移步至 🔜🔜🔜 https://blog.csdn.net/mr_zhuqiang/article/details/45917551
关于线程 isInterrupted()
大家可以移步至 🔜🔜🔜 https://leixiaoheng.blog.csdn.net/article/details/126423041
三. 线程的分类
-
Java中的线程分为两类:一种是守护线程 ,另一种是 用户线程 。
-
它们在几乎每个方法都是相同的,唯一的区别是判断 JVM 何时离开。
-
默认创建的线程没有特殊处理的话,就是一个用户线程 , main 主线程就是一个用户线程
-
守护线程: 是用来服务用户线程的,通过在
start()
方法前调用,thread.setDaemon(true)
可以将一个用户线程变成一个守护线程。注意是:在 start() 方法创建新线程之前,调用thread.setDaemon(true)
对象方法,不然会报:IllegalThreadStateException
非法线程状态异常 -
Java 垃圾回收就是一个典型的守护线程。
-
守护线程的特点: 当所有用户线程都结束了,守护线程会自动结束。用户线程不会 。
-
守护线程用在什么地方呢 ???
- 每天 0:00 的时候,系统数据自动备份。这个需要使用到定时器,并且我们可以将定时器设置为守护线程,一直在哪里看着,每到 0.00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。
- 每天 0:00 的时候,系统数据自动备份。这个需要使用到定时器,并且我们可以将定时器设置为守护线程,一直在哪里看着,每到 0.00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。
举例:创建一个用户线程:main 主用户线程,和一个 守护线程 : t1 ,在main 主用户线程中定义一个当 for(int i )循环 中的 i == 5时,抛出 int num = 1/0; 的算数异常终止 main 主用户线程的执行。同样的 t1 守护线程也会停止
package blogs.blog4;
/**
* 守护线程的设置
*/
public class ThreadTest12 {
public static void main(String[] args) {
Thread t1 = new Thread(new MyThread12());
t1.setName("t1 用户线程");
// 将用户线程修改为 守护线程
t1.setDaemon(true);
Thread.currentThread().setName("main 主线程");
// 创建新线程
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
if (i == 5) {
int num = 1 / 0; // 让main 主用户线程异常终止
}
}
}
}
class MyThread12 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
try {
Thread.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
如果两个是用户线程,各自执行各自的线程的(弹栈压栈),互不影响,就是 main 主用户线程终止,其他用户线程也不会终止。
package blogs.blog4;
/**
* 守护线程的设置
*/
public class ThreadTest12 {
public static void main(String[] args) {
Thread t1 = new Thread(new MyThread12());
t1.setName("t1 用户线程");
Thread.currentThread().setName("main 主线程");
// 创建新线程
t1.start();
// main 主用户线程
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
if (i == 5) {
int num = 1 / 0; // 让main 主用户线程异常终止
}
}
}
}
class MyThread12 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
try {
Thread.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
四. 线程的定时器
定时器的使用指定定时任务:
定时器的作用: 间隔特定的时间,执行特定的程序,每周要进行银行账户的总账操作。
在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的,
那么在Java中其实可以采用多种方式实现:
可以使用sleep 方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务,这种方式是最中原始的定时器 (比较Low)
在Java的类库种已经写好了一个定时器,ava.util.Timer
可以直接拿来用。不过,这种方式在目前的开发中也很少用,因为现在有很多高级框架都是支持定时任务的。
在实际开发中,目前使用较多的是Spring框架中提供的SpringTask框架,这个框架只要进行简单的配置,就可以完成定时器的任务。
步骤:
- 创建一个 extends abstract TimerTask 抽象类的子类,并重写其中 TimerTaskimplement Runnable 的 run () 方法。
class LogTimerTask extends TimerTask {
// 2. 重写 Runnable 中的 run()方法
@Override
public void run() {
// 编写你需要执行的任务就行了
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strTime = simpleDateFormat.format(new Date()); // 现在的时间点
System.out.println(strTime + ": 成功完成了一次数据备份");
}
}
因为 TimerTask是 implement Runnable 接口的
public abstract class TimerTask implements Runnable {
}
- 创建定时器
Timer
的 实例对象
Timer timer = new Timer();
也可以创建守护线程(当用户线程结束了,守护线程自动结束)的方式创建定时器对象 Thread 对象
Timer timer2 = new Timer(true);
Timer 对于的构造器
- 指定:定时任务 调用 timer.schedule()对象方法
public void schedule(TimerTask task, Date firstTime, long period);
// timer.schedule(定时任务,第一次执行时间,间隔多久执行一次(单位:毫秒));
/*
1000 *60 一分钟
1000 * 60 * 60 一个小时
1000 * 60 * 60 *24 一天
1000 * 60 * 60 * 24 * 365 一年
*/
完整实现步骤如下:
package blogs.blog4;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* 定时器
*/
public class ThreadTest13 {
public static void main(String[] args) {
// 3.创建定时器对象
Timer timer = new Timer();
// 这里我们也可以创建守护线程(当用户线程结束了,守护线程自动结束)的方式创建定时器对象
Timer timer2 = new Timer(true);
// 4.指定:定时任务 调用 timer.schedule()对象方法
// timer.schedule(定时任务,第一次执行时间,间隔多久执行一次(单位:毫秒));
// 设置时间类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date firstTime = null;
try {
firstTime = sdf.parse("2023-01-11 21:25:10");
} catch (ParseException e) {
e.printStackTrace();
}
timer.schedule(new LogTimerTask(), firstTime, 1000 * 10); // 间隔十秒
}
}
// 编写一个定时任务类
// 假设是一个记录日志的定时任务
// public abstract class TimerTask implements Runnable
// 1.创建一个 extends TimerTest 类的子类
class LogTimerTask extends TimerTask {
// 2. 重写 Runnable 中的 run()方法
@Override
public void run() {
// 编写你需要执行的任务就行了
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strTime = simpleDateFormat.format(new Date()); // 现在的时间点
System.out.println(strTime + ": 成功完成了一次数据备份");
}
}
五. 总结:
- 对于线程的优先级的使用 Thread 类中的
getPriority()
获取当前线程的优先级和setPriority(int newPriority)
设置线程的优先级。 - 线程的优先级是在 [10~1] 之间的,其中 5 是默认线程的优先级。当所设置的线程优先级,不再 [10~1] 这个区间内报:
IllegalArgumentException
非法参数异常。 - 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用,高优先级的线程也不是一定就比低的优先级线程先执行,只是先被执行的概率更高而已,注意是 概率不是绝对 。
- 守护线程: 是用来服务用户线程的,通过在
start()
方法前调用,thread.setDaemon(true)
可以将一个用户线程变成一个守护线程。注意是:在 start() 方法创建新线程之前,调用thread.setDaemon(true)
对象方法,不然会报:IllegalThreadStateException
非法线程状态异常 - 默认创建的新线程是用户线程 main 是用户线程,Java 中的 垃圾回收线程是守护线程。
- 守护线程的特点: 当所有用户线程都结束了,守护线程会自动结束。用户线程不会 。
- 定时器的作用: 间隔特定的时间,执行特定的程序,每周要进行银行账户的总账操作。
六. 最后:
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!