【JAVA】多线程(3)线程状态

本文详细探讨了Java中的守护线程( daemon threads)、礼让线程(yielding)以及线程的睡眠、加入和优先级设置。守护线程在JVM退出时自动结束,守护线程示例和礼让线程行为对比鲜明。线程的t.sleep()用于延迟执行,t.join()确保主线程等待子线程完成。最后,讲解了线程优先级的概念及其在实际中的应用。
摘要由CSDN通过智能技术生成

1、守护线程 t.setDaemon(true)

守护线程相对于正常线程来说,是比较特殊的一类线程,守护线程是服务提供者线程。

Java官方文档:

The Java Virtual Machine exits when the only threads running are all daemon threads.

当 JVM 中不存在任何一个正在运行的非守护线程时,则 JVM 进程即会退出。

  • **①:**创建一个非守护线程;
  • **②:**模拟非守护线程不退出的情况;
  • **③:**启动线程;
  • **④:**主线程即将退出;

从下面的例子进行理解:

public class NoDaemonTeat {
    public static void main(String[] args) {
        Thread t = new Thread(NoDaemonTeat::print);
        t.setDaemon(false);
        t.start();
        System.out.println("Exiting main  method");
    }
    public static void print() {
        int counter = 1;
        while (true) {
            try {
                System.out.println("Counter:" + counter++);
                Thread.sleep(2000); // sleep for 2 seconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出:

Counter:1
Exiting main method
Counter:2
Counter:3
Counter:4
Counter:5
Counter:6

…………

从输出结果看,主线退出,而非守护线程不退出,正因为有一个非守护线程一直在后台运行着,JVM 无法正常退出。

现在我们试一试开启守护线程,并设计一个钩子线程,用于监听JVM:

public class NoDaemonTeat {
    public static void main(String[] args) {
        //设计一个钩子线程,用于监听JVM
        Runtime.getRuntime().addShutdownHook(new Thread(()->System.out.println("The JVM is exited")));
        Thread t = new Thread(NoDaemonTeat::print);
        t.setDaemon(true);
        t.start();
        System.out.println("Exiting main  method");
    }
    public static void print() {
        int counter = 1;
        while (true) {
            try {
                System.out.println("Counter:" + counter++);
                Thread.sleep(2000); // sleep for 2 seconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出结果:

Counter:1
Exiting main method
The JVM is exited

这时主线程退出,JVM也同时退出了。

以上可知:守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点

应用:通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时,或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。

例如:JVM 中的垃圾回收线程就是典型的守护线程。

2、礼让线程 t.yield()

礼让不一定成功,看CPU心情

//测试礼让线程
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"a").start();
        new Thread(myYield,"b").start();
    }


}

class MyYield implements Runnable{
    @Override
    public void run() {
       System.out.println(Thread.currentThread().getName()+"线程开始");
       Thread.yield();
       System.out.println(Thread.currentThread().getName()+"线程结束");

    }
}

结果:

a线程开始
b线程开始
a线程结束
b线程结束

3、线程睡眠 t.sleep()

很好理解,就是线程延时。

import java.text.SimpleDateFormat;
import java.util.Date;
//获取并更新系统时间
public class TestSleep {
    public static void main(String[] args) {
        Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

4、线程加入 t.join

在JDk的API里对于join()方法是:

join 

public final void *join()* throws InterruptedException Waits for this thread to die. Throws: InterruptedException - if any thread has interrupted the current thread. The *interrupted status* of the current thread is cleared when this exception is thrown.

public final void join() throws InterruptedException等待线程死亡。抛出:InterruptedException——如果有线程中断了当前线程。当抛出这个异常时,当前线程的“中断状态”将被清除。

简单的说,就是在子线程调用join后,主线程应等待子线程完成,才继续进行。

用途:子线程需要大量运算的时候。

public class TestJoin implements Runnable{
    @Override
    public void run() {
        System.out.println("线程VIP" );
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin =new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        for (int i=0;i<100;i++){
            if (i==20){
                thread.join();
            }
            System.out.println("main"+i);
        }

    }

}

输出结果:

main0
……
main19
线程VIP
main20

…………

main99

5、线程优先级

在Java程序设计语言中,每一个线程有一个优先级。默认情况下,一个线程会继承构造它的那个线程的优先级。可以用 setPriority方法提高或降低任何一个线程的优先级。可以将优先级设置为MIN PAIORITY (在Thread 类中定义为1)与 MX PRIORLITY (定义为10)之间的任何每当线程调度器有机会选择新线程时,它首先选择具有较高优先级的线程。但是,线程优先级高度依赖于系统。当虚拟机依赖于宿主机平台的线程实现时,Java线程的优先级会映射到宿主机平台的优先级,平台的线程优先级别可能比上述的10个级别多,也可能更少。
例如,Windows有7个优先级别。Java的一些优先级会映射到同一个操作系统优先级。
在Oracle为Linux提供的Java虚拟机中,会完全忽略线程优先级——所有线程都有相同的优
在没有使用操作系统线程的Java早期版本中,线程优先级可能很有用。不过现在不要使用优先级了。
void setPriority(int newPriority)

设置线程的优先级。优先级必须在Thread.MIN_PRIORITY与Thread.MAX PRIORITY之间。一般使用Thread.NORM_PRIORITY优先级。
是Thread可以有的最小优先级。最小优先级的值为1。
Thread 的默认优先级。默认优先级为5。
是Thread可以有的最大优先级。最大优先级的值为10。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值