多线程(十六):创建并启动线程和终止线程


prtyaa
prtyaa 2023-12-28 16:52:04 52370 赞同 0 反对 0
分类: 资源
启动线程的方法只有一种

直接new

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("打印。。。。");
            }
        };
        t.start();
    }
}

继承Thread,重写run方法

下来看Runnable和Callable

Callable怎么get值呢?


stop方法终止线程,但是破坏原子性,把线程直接就干死了

interrupt方法并不是终止线程,如果t1线程调用了interrupt方法,那么t1线程的Isinterrupted属性就是true。 那么我们while循环的时候肯定是while(!..) 这样判断的。

还有就是走catch代码块,因为interrupt要抛异常,之前文章里写过。

 

下图会看到一个线程的isInterrupted状态是false的,线程状态是Runnable的

 

让我们调用一下interrupt方法看看,一秒钟之后isInterrupted属性变成了true,注意这里并没有终止线程,一直是循环的。有人会问了,为什么没有抛异常呢? 当线程的状态是Runnable的时候,调用t.interrupt()时,是不会抛异常的,除非你的状态时waiting /Timed waiting的时候才会抛异常

 

注意了: 上述isInterrupted状态的改变都是基于线程是Runnable状态的时候,未调用interrupt方法之前,isInterrupted状态是false,调用interrupt方法之后,isInterrupted状态是true。

但是这些都是基于线程是Runnable状态的时候。当线程处于waiting,Timed waiting的时候,调用interrupt方法之后,再catch块里isInterrupted状态是false。

(后话Thread.currentThread().interrupt()又会把状态变成true)

start之后,主线程睡了1秒,所以执行权交给t, 然后t开始运行 打印try块里的代码,t睡了0.2秒,这时候执行权交给主线程,因为主线程睡了1秒,所以t睡了0.2秒之后,主线程得到执行权还在睡,所以过了0.2秒之后t醒了,打印try-catch之外的代码,反复这样循环,直到主线程醒了之后,主线程执行t.interrupt方法,子线程如果sleep的时候,则把子线程t的timed waiting状态清除,t变成Runnable状态,可以被执行,同时因为主线程执行t.interrupt方法,所以t进入catch块,catch块结束之后,继续打印后面的代码,然后继续while循环,再也不进catch块了,因为会进try块,try块里面会sleep。sleep了之后,又没有interrupt了,因为t.interrupt只执行了一次。然后反复try块的代码和try-catch之外的代码。这样子运行

那么如何停止呢?

很简单,while(Thread.currentThread().isInterrupted()) 就好了 ,根据这个判断

还是上面的图,异常之后catch块里的 isInterrupted成了false,那么如果再加上Thread.currentThread().interrupt() 那么isInterrupted属性就又变成了true,有点绕,还是多用代码测试就知道了。


另外上面之所以会循环打印,是因为sleep了。时间过了后,就继续运行了。但是wait后可不继续运行,那就挂起了,放弃了执行资格,也放弃了锁,直到有人唤醒他。还有wait必须用在同步中。

有一个bug 就是LockSupport的park方法,也是挂起,但是interrupt之后,park方法会失效,不再挂起,看下图,我是正在运行的时候截的图,这个代码是死循环的。本来是t.interrupt()之后,打印一次2333,然后再进来park后挂起,后面就不再输出2333了,但是park不是wait,park有诡异的事情发生就是失效了。

 

这是wait,会看到第一次会打印wait前。然后挂起,遇到interrupt()打断之后。并不会输出wait后,因为interrupt()会运行catch块代码666,然后继续运行2333,然后继续循环,打印了wait前,然后挂起,不动了(没有了interrupt(),因为interrupt()只执行了一次)这和park就是区别。 park挂起操作失效了,会死循环。

 

题外话: 太智能了,居然检测到编译错误。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
prtyaaL2
粉丝 1 资源 1949 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  125
统信桌面专业版【全盘安装UOS系统】介绍  120
银河麒麟桌面操作系统安装佳能打印机驱动方法  111
银河麒麟桌面操作系统 V10-SP1用户密码修改  105
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益209.03元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!