Java-解读

Interrupt与sleep

2019-07-22  本文已影响0人  可爱猪猪

作者:可爱猪猪 - 帅锅一枚
作者的网名很阔爱,如果喜欢本文章一定要点 喜欢 或者 打赏,拜托~
作者一直在进步,需要你们的支持和鼓励,谢谢!
人生理想:在程序猿界混出点名堂!

好了,先看看面这个例子,如何停止一个线程

public class LazyThread extends Thread{
    // 是否被打扰
    public static volatile boolean interrupted = false; 
    public void run() {
        // 没有被打扰就继续吃
        while(!interrupted) {
            System.out.println("eat...");
        }
        // 打扰后唤醒
        System.out.println("wake up...");
    }
    public static void main(String[] args) {
        
        Thread lt = new LazyThread();
        lt.start();
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("wake up");
        LazyThread.interrupted = true;
    }
}

我们采用了一个标志,来中断这个线程,可是这种方式有个问题,如果LazyThread存在sleep 或者Thread.join根本中断不了,好了,废话不多少,看下面这个例子


public class LazyThread extends Thread{
    // 是否被打扰
    public void run() {
        
        // 没有被打扰就继续吃
        while(!Thread.currentThread().isInterrupted()) {
            System.out.println("eat...");
            
            // 这个线程真的很懒,不断的吃和睡
            try {
                TimeUnit.SECONDS.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
        }
        
        // 打扰后唤醒
        System.out.println("wake up...");
    }
    
    
    public static void main(String[] args) {
        
        Thread lt = new LazyThread();
        lt.start();
        
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("wake up");
        lt.interrupt();
    }
}

看一下这个,去掉LazyThread的sleep 30秒的代码,这个代码没有什么问题,但是呢,我们这个本来是要终止sleep阻塞的,可是虽然中断了sleep,然而线程的interrupted状态依然是【非中断】,看如下运行结果:

Result1.png

始终阻止不了这个lazy线程的吃操作....
于是我们还是看下JDK的代码:


  /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;

看到native方法不要着急,我们看下注释:如果任意线程已经中断了当前线程,这个interrupt状态会被清除,会抛出一个异常。
瞬间恍然大悟。

状态被清除了

好了,那该怎么办呢?

《JAVA并发编程实战》一书中其实给出了答案,对于Interrupt异常,有两种处理方式:
1.捕捉异常后,重新调用Thread.currentThread.interrupt();来修改异常状态 ,以便我们的线程的interrupt状态能被捕获,而退出循环
2.抛出异常

后语:
interrupt()方法只是打了一个标记告诉线程,线程自行处理
sleep被interrupt后,是会清除interrupt状态的。

上一篇下一篇

猜你喜欢

热点阅读