作者简介: zoro-1,目前大二,正在学习Java,数据结构,mysql,数据结构,javaee等
作者主页: zoro-1的主页
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
Thread的基础用法
- 属性
- ID
- 名称
- 状态
- 优先级
- 是否是后台进程
- 是否存活
- 是否被中断
- 方法一:利用一个boolean类型变量
- 方法二:利用Thread自带的api来操作
- **sleep为什么要清除标志位呢?**
- 等待线程
- sleep
- join
属性
ID
jvm自动分配的身份标识,不重复
名称
当前线程的名字,可以通过Thread的构造方法设置,可以重复
状态
• NEW:安排了⼯作,还未开始⾏动
• RUNNABLE:可⼯作的.⼜可以分成正在⼯作中和即将开始⼯作.
• BLOCKED:这⼏个都表⽰排队等着其他事情(锁竞争引起)
• WAITING:这⼏个都表⽰排队等着其他事情(”死等“,以及wait引起)
• TIMED_WAITING:这⼏个都表⽰排队等着其他事情(sleep,超时join引起)
• TERMINATED:⼯作完成了.
优先级
在操作系统中,线程有不同的优先级来控制它们的调度。优先级定义了线程在争夺CPU时间时的优先级顺序。通常,操作系统会按照优先级最高的线程先执行,然后是优先级次高的线程,以此类推,直到所有线程都执行完毕或者被暂停。
是否是后台进程
后台进程
不会阻止进程的结束
前台进程
会组止进程的结束
需要在调用start方法前调用setDaemon()方法设置是否为后台进程,
手动创建的线程都是前台进程
是否存活
JAVA代码中定义的线程对象的生命周期与内核中的pcb生命周期是不一样的
下面我们用一个代码演示一下
public class ThreadText3 {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
System.out.println("这个线程正在运行");
});
System.out.println(thread.isAlive());
thread.start();
System.out.println(thread.isAlive());
thread.join();
System.out.println(thread.isAlive());
}
}
通过上述代码我们可以发现thread这个线程在创建前不在内核中存活和调用start方法后才在内核上创建pcb存活,等他执行结束后就不存活了
是否被中断
方法一:利用一个boolean类型变量
public class ThreadText3 {
static boolean flag=false;
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
while (!flag){
System.out.println("线程正在运行");
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
sleep(10000);
flag=true;
System.out.println("线程结束");
}
}
方法二:利用Thread自带的api来操作
import static java.lang.Thread.sleep;
public class ThreadText4 {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("线程正在运行");
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
Thread.sleep(1000);
//停止线程
thread.interrupt();
System.out.println("线程结束");
}
}
上述代码执行完毕,发现不能停止线程,这是为什么呢?
这是因为如果interrupt()执行时,t线程正在sleep,那么interrupt()在将标志位设置为true后,又会直接将sleep强行唤醒。sleep在该程序中,占据了绝绝绝大部分的时间,因此当interrupt()执行时,几乎一定会遇到正在sleep的情况。注意:当sleep被提前唤醒的时候,sleep会自动把isInterrupted标志位再次清空(即把true又变为false)。这就导致了下次再判断循环条件,循环条件还成立,因此循环还在继续执行。
这么做的目的是为了让线程自身能够对于线程何时结束有一个更明确灵活的控制。
sleep为什么要清除标志位呢?
事实上,当前interrupt方法的效果并不是让线程立即结束,而是“通知建议”性质的,告诉线程“你该结束了”。至于线程是否真的要立即结束,都是可以通过代码来灵活控制的,否则就太僵硬了。interrupt只是通知,而不是命令。
比如有一天你正在打游戏,你的妈妈突然喊你去超市买酱油。这时你可以灵活选择:1、等一会儿再去;2、直接忽视;3、立马就去。代码也是一样:
等待线程
多线程的执行顺序是无序的(随机调度),但我们想通过一些方式让他有序怎么办
sleep
等待第一个线程结束后再执行第二个线程,首先我们要知道第一个线程执行多长时间,通常我们是不知道多长时间的,所以这个方法不常用
import static java.lang.Thread.sleep;
import static java.lang.Thread.sleep;
public class ThreadText4 {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("线程正在运行");
try {
sleep(100);
} catch (InterruptedException e) {
break;
}
}
});
thread.start();
Thread.sleep(1000);
//停止线程
thread.interrupt();
System.out.println("线程结束");
}
}
join
public class ThreadText4 {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
System.out.println("线程正在运行");
}
);
thread.start();
thread.join();
System.out.println("线程结束");
}
}
thread执行时main处于阻塞状态,等thread执行结束后才去cpu上参与调度,join通常用于多个线程并发执行主线程等待他们执行完毕,然后汇总
今天的分享到这里就结束了,感谢大家支持