android studio kotlin 新线程_死循环


直接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方法


android studio kotlin 新线程_死循环_02


下来看Runnable和Callable


android studio kotlin 新线程_主线程_03


Callable怎么get值呢?


android studio kotlin 新线程_主线程_04




android studio kotlin 新线程_主线程_05


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

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

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

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


android studio kotlin 新线程_子线程_06


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


android studio kotlin 新线程_kotlin 子线程睡3秒_07


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

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

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


android studio kotlin 新线程_主线程_08


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有诡异的事情发生就是失效了。


android studio kotlin 新线程_死循环_09


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


android studio kotlin 新线程_主线程_10


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


android studio kotlin 新线程_kotlin 子线程睡3秒_11