首页 > 编程语言 >Java多线程02——线程的生命周期和状态调度

Java多线程02——线程的生命周期和状态调度

时间:2023-02-05 22:31:57浏览次数:49  
标签:02 状态 Java Thread void 线程 println 多线程 public

1 线程的生命周期

在线程的生命周期中,要经过新建​​new​​、就绪​​runnable​​、运行​​running​​、阻塞​​blocked​​和死亡​​dead​​ 5种状态。

当线程启动后,它不可能一直“霸占”CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行和阻塞之间切换。

线程的生命周期五个阶段

Java多线程02——线程的生命周期和状态调度_多线程

1、新建状态,当程序使用​​new​​关键字创建了一个线程之后,该线程处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值。

2、就绪状态,当线程对象调用了​​start​​方法后,该线程处于就绪状态。java虚拟机会为其创建方法调用栈和程序计数器,等待调试运行。

3、运行状态,如果处于就绪状态的线程获得了CPU,开始执行run方法的线程执行体,则该线程处于运行状态。

4、阻塞状态,当处于运行状态的线程失去所占用资源之后,便进入阻塞状态。

5、死亡状态,在线程的生命周期当中,线程执行完成之后的最终状态。

2 线程的休眠

线程休眠的方法是 ​​Thread.sleep(long millis)​

线程休眠的目的是使线程让出CPU的最简单做法之一,线程休眠的时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入就绪状态等待执行。

简单说,哪个线程调用​​sleep()​​方法,就休眠哪个线程。

3 线程的让步

​yield()​​的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权。

但是,并不能保证在当前线程调用​​yield()​​之后,其它具有相同优先级的线程就一定能获得执行权;也有可能当前线程又进入到“运行状态”继续运行。

简单的说,就是哪个线程执行​​yield​​方法,就是礼让。

public class UserThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " :A");

Thread.yield();

System.out.println(Thread.currentThread().getName() + " :B");
}
}

4 线程的合并

线程的合并作用,就是将几个并行线程合并为一个单线程执行。

当一个线程必须等待另一个线程执行完毕才能执行时,可以使用​​join()​​方法。

public class UserThread extends Thread {
@Override
public void run() {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName() + "执行" + i + "次");
}
}
}
public class Test {
public static void main(String[] args) {
UserThread userThread = new UserThread();
userThread.start();

for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName() + "执行" + i + "次");

//将子线程合并到主线程中
try {
userThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

5 守护线程

调用线程对象的方法 ​​setDaemon(true)​​ ,可以将其设置为守护线程。

JVM的垃圾回收、内存管理等线程都是守护线程。

​setDaemon(boolean on)​​ 将该线程标记为守护线程或用户线程,该方法必须在启动线程前调用。

当正在运行的线程都是守护线程时,java虚拟机就会退出。

public class Backend extends Thread {
@Override
public void run() {
for(int i=0;i<8888;i++){
System.out.println("后端执行" + i + "次");
}
}
}
public class Front extends Thread {
@Override
public void run() {
for(int i=0;i<3;i++){
System.out.println("前端执行" + i + "次");
}
}
}
public class Test {
public static void main(String[] args) {
Backend backend = new Backend();
Front front = new Front();

//设置后台为守护线程
backend.setDaemon(true);

backend.start();
front.start();
}
}

当非守护线程执行完成后,jvm就会停止运行。

6 线程的中断和死亡

6.1 线程中断

线程中断就是让目标线程停止执行,但它不会使线程立即终止,而是给线程发送一个通知,告诉线程JVM希望退出执行,至于目标线程何时退出,完全由JVM自己决定。

public class UserThread {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
while (true){
//判断当前线程是否处于中断状态
if(this.isInterrupted()){
System.out.println(Thread.currentThread().getName() + " 处于中断状态");
break;
}
}
}
};

thread.start();

try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}

//调用线程的中断方法
thread.interrupt();
}
}

6.2 线程死亡

线程会以如下三种方式结束,结束后就处于死亡状态:

  • ​run()​​ 或 ​​call()​​ 方法执行完成,线程正常结束;
  • 线程抛出一个未捕获的 ​​Exception​​ 或 ​​Error​​;
  • 直接调用线程的​​stop()​​方法结束线程,该方法容易导致死锁,不建议使用

注意:

不能对一个已经死亡的线程调用​​start()​​方法,因为死亡线程已不再可用。

public class Test {
//线程退出标记
public static boolean exit = false;

public static void main(String[] args) {
new Thread(){
@Override
public void run() {
System.out.println("线程启动了");
while (!exit){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程结束了");
}
}.start();

//等待5秒,修改线程结束标记
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

exit = true;
}
}


标签:02,状态,Java,Thread,void,线程,println,多线程,public
From: https://blog.51cto.com/u_113754/6038500

相关文章