【JavaSE】多线程篇(3)线程终止,线程插队与线程状态

文章介绍了Java中线程的两种终止方法:通过自定义变量和使用Thread的中断标志位。还讲解了线程插队(yield和join)以及线程的五种状态:新创建、运行、阻塞、等待和终止。示例代码展示了如何在实际操作中应用这些概念。
摘要由CSDN通过智能技术生成


线程终止

1.当线程完成任务后,会自动退出。
2.还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式
本质上来说让一个线程终止,办法就一种 让该线程的入口方法执行完毕

方法一 自己创建一个变量来结束循环

代码演示:

package Thread;

public class ThreadDemo9 {
    public static boolean isQuit=false;//使用成员变量
    public static void main(String[] args) {
        //boolean isQuit=false; 变量捕获
        Thread t=new Thread(()-> {
            long start=System.currentTimeMillis();
            while (!isQuit){
                System.out.println("hello t");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t 线程终止");
            long end=System.currentTimeMillis();
            System.out.println("运行时间"+( end-start));
        });
        t.start();
        // 在主线程中, 修改 isQuit
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isQuit=true;
    }
}

tmp2F98.png

方法二 使用Thread内置的标志位

tmp3B6E.png

package Thread;

public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread t=new Thread(()-> {
            // currentThread 是获取到当前线程实例.
            // 此处 currentThread 得到的对象就是 t
            // isInterrupted 就是 t 对象里自带的一个标志位.
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;//结束循环
            }
        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();//把t内部的标志位设置成true
    }
}


interrupt方法的作用:
1.设置标志位为true
2.如果该线程正在阻塞中(比如在执行sleep)此时就会把阻塞状态唤醒。通过抛出异常的方式让sleep立即结束

注意一个非常重要的问题
当sleep被唤醒的时候,sleep会自动的把islnterrupted标志位给清空(true->false)
这就导致下次循环,循环仍然可以继续执行了
如果需要结束循环需要在catch中加break

sleep被唤醒机制
如果sleep执行的时候看到isInterrupt标志位是false
sleep正常进行休眠操作
如果当前isInterrupt标志位为true
sleep无论是刚刚执行还是已经执行了一半,都会触发两件事
1.立即抛出异常
2.清空标志位为false再下次循环,到sleep,由于当前标志位本身就是false,就没有影响了

线程插队

1.yield:线程的礼让 让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功
2.join:线程的插队 插队的线程一旦插队成功,则肯定先执行完插入的线程所有的任务
只有确定的方法才让人安心,因此线程插队主要通过join来实现
代码演示:

package Thread;

public class ThreadDemo11 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            System.out.println("hello t");
        });
        t.start();
        t.join();//main线程等待t先结束
        System.out.println("hello main");
    }
}

tmp605C.png
在main线程中,调用t.join意思就是让main线程等待t先结束,再往下执行
1.main线程调用t.join的时候,如果t还在运行,
此时main线程阻塞,直到t执行完毕(t的run执行完了),main才从阻塞中解除,才继续执行
2.main线程调用t.join的时候,如果t已经结束了,
此时join不会阻塞,就会立即往下执行

线程的状态

新创建状态 new

新创建了一个线程对象,但还没有调用start()方法

运行状态 runnable

Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”

阻塞状态 blocked

阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态

等待状态 waiting

处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒(调用notify方法或notifyAll方法),否则会处于无限期等待的状态

超时等待状态 timed_waiting

处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒

终止状态 terminated

表示该线程已经执行完毕
当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了
tmpBFC0.png

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值