Java多线程--正确理解interrupt()、interrupted()和isInterrupted()

1.interrupt()

理解这个函数,可以首先从它自己的JavaDoc入手。

Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread’s interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.
If this thread is blocked in a java.nio.channels.Selector then the thread’s interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector’s wakeup method were invoked.
If none of the previous conditions hold then this thread’s interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.

根据文档,可以看出interrupt()函数所做的是形式上中断一个线程。

为什么说是形式上的中断,因为这个函数不会去真正意义上的打断一个正在运行的线程,而是修改这个线程的中断状态码(interrupt status)。同时,对于处在sleep()、wait()和join()方法阻塞下的线程,该方法会使线程抛出一个异常。对于可中断通道(NIO中的Channel)的阻塞状态,该方法会关闭通道,抛出异常。对于NIO中选择器的阻塞(Selector.selector),该方法等同于调用选择器的wakeup()方法。

也就是说,Java并不希望你暴力的去杀死一个线程(因为Java线程是基于操作系统的,而操作系统是可以直接杀死一个进程的),而是希望你通过优良的设计实现一种优雅的中断方式。(这个我们以后再说)

public class InterruptTest {

    public static void main(String[] args) {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println(Thread.currentThread().getName()+" 依旧在运行");
                }
            }
        });

        thread.start();
        // 执行线程的interrupt()方法
        thread.interrupt();
    }

}

我们会发现线程依旧在运行。
这里写图片描述

2.isInterrupted()

这个方法会返回线程的中断标志位。

    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                }
            }
        });

        thread.start();
        System.out.println(thread.isInterrupted());
        thread.interrupt();
        System.out.println(thread.isInterrupted());

这里写图片描述
可以看到,调用某一个线程对象的isInterrupted()方法会返回该线程的中断状态码。调用interrupt()方法以后,会改变这个线程的中断状态码。

3.interrupted()

这个方法会返回当前线程的中断标志位,同时会重置中断标志位。

public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                    if (Thread.interrupted()) {
                        System.err.println("线程中断标志位为true");
                    }
                }
            }
        });
        System.out.println(thread.isInterrupted());
        thread.start();     
        thread.interrupt();
        System.out.println(thread.isInterrupted());
    }

这里写图片描述

可以看出:

  1. 该方法是一个Thread类的静态方法,调用时会返回当前线程的中断状态码。
  2. 调用完该方法以后,中断状态码会被重置。

从源码可看出:

    // Thread.interrupted()
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

其实就是调用了当前线程的isInterrupted(boolean ClearInterrupted)方法,根据JavaDoc很容易理解, 这个native方法的参数如果为true,则会重置(reset)中断状态码。

猜你喜欢

转载自blog.csdn.net/cringkong/article/details/80526996