关于线程中断interrupt()、谦让yield()、等待线程结束join()

关于interrupt()

表面上看中断就是让目标线程停止执行的意思,实际上并非完全如此。

严格上讲,线程中断并不会使线程立即退出,而是给线程发送一个通知,告知目标线程有人希望你退出,至于目标线程接到通知后如何处理,则完全由目标线程自行决定。

interrupt()方法的作用实际上是:在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞状态。换句话说,没有被阻塞的线程,调用interrupt()方法是不起作用的。

关于线程的3个重要方法:

interrupt():通知目标线程中断,设置中断标志位。中断标志位表示当前线程已经被中断了。

isInterrupted():判断当前线程是否被中断(通过检查中断标志位)。

interrupted():判断当前中断状态,但同时清除了当前线程的中断标志位状态。

如果希望某线程在中断后退出,就必须为它增加响应的中断处理代码。

如下:

public class Main {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("run...");
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("interruptd...");
                        break;
                    }
                    Thread.yield();
                }
            }
        };
        t1.start();
        Thread.sleep(2000);
        t1.interrupt();
    }
}

关于yield()

让当前线程让出CPU(并不代表当前线程不执行了),让出CPU后还会进行CPU资源的争夺,但是是否能够再次被分配到,就不一定了。

如果觉得某个线程不是那么重要,或者优先级非常低,有害怕它会占用太多的CPU资源,那么可以在适当的时候调用此方法,给予其他重要线程更多的工作机会。

关于join()

join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远wait,代码片段如下,wait(0)表示永远等待下去。

while(isAlive()){

wait(0);

}

直到join线程中止后,线程的this.notifyAll会被调用,调用notifyAll是在JVM里实现的,所以JDK里看不到,有兴趣的同学可以看看JVM源码。JDK不推荐在线程实例上使用wait,notify和notifyAll方法。(参考:http://ifeve.com/talk-concurrency-countdownlatch/)可以用CountDownLatch异步转同步操作。

与sleep的区别:sleep(2000)不释放锁,join(2000)释放锁,因为join()方法内部使用的是wait(),因此会释放锁。

猜你喜欢

转载自my.oschina.net/u/2939155/blog/1632880