中断的作用:如果线程A正在阻塞,线程B 想要提前结束线程A 的 阻塞状态,则可以通过中断机制来做通知。

java 中断依赖于 3个方法,interrupt(),isInterrupted()和interrupted()。中断状态为true和false 

  • interrupt()  设置中断状态为true。 A中调用线程B的interrupt()方法,即会向线程B发出信号(线程中断状态已被设置),如果线程B正在执行中没有可以中断的方法,可以通过判断中断状态来决定是否继续执行,这个时候获取中断状态,会返回true,如果线程B是可中断的阻塞状态,则会抛出中断异常。我们可以通过catch 异常进行业务处理。这个时候获取中断状态,会返回false.因为抛出异常的时候,虚拟机清除了中断状态。
  • isInterrupted() 用来获取调用线程的中断状态
  • interrupted()     是Thread的static方法,用来清除当前线程的中断状态,这个时候获取中断状态,第一次返回的是当前线程的中断状态,第二次返回false. 例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

       另外如果线程B 没有可以中断的方法,被中断了,这个线程需要判断中断状态,然后继续执行,如果处理之后想要清除中断状态,可以调用interrupted()  方法,这样 线程B可以被再次中断。

注意:interrupt()线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(sleep、wait等 也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了,就是说我们调用该线程的isInterrupted 方法时是返回false。如果你想保持中断状态,可以再次调用interrupt方法设置中断状态,然后通过其他逻辑来处理中断。

清除中断状态的方法?

1 线程停止运行 2没有抛出中断异常 3 清除中断状态interrupted()

interrupted 和 isInterrupted的区别?

首先看一下该方法的实现:

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

该方法就是直接调用当前线程的isInterrupted(true)方法。

然后再来看一下 isInterrupted的实现:public boolean isInterrupted () {return isInterrupted( false);}

这两个方法有两个主要区别:

  1. interrupted 是作用于当前线程   isInterrupted 是作用于调用该方法的线程对象所对应的线程
  2. 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;

第二个区别主要体现在调用的方法的参数上,让我们来看一看这个参数是什么含义

先来看一看被调用的方法 isInterrupted(boolean arg)的定义:private native boolean isInterrupted( boolean ClearInterrupted);

原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。

如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成false)。这个参数为false,就是直接返回线程的状态位。

interrupt()是用来设置中断状态的。返回true说明中断状态被设置了而不是被清除了。
interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

接下来,看看具体在代码中如何使用。

interrupt()不能中断在运行中的线程,它只能改变中断状态而已。

public class InterruptionInJava implements Runnable{

    public static void main(String[] args) throws InterruptedException {

        Thread testThread = new Thread(new InterruptionInJava(),"InterruptionInJava");

        //start thread

        testThread.start();

        Thread.sleep(1000);

        //interrupt thread

        testThread.interrupt();

        System.out.println("main end");

    }

    @Override

    public void run() {

        while(true){

            if(Thread.currentThread().isInterrupted()){

                System.out.println("Yes,I am interruted,but I am still running");

            }else{

                System.out.println("not yet interrupted");

            }

        }

    }

}

 结果显示,被中断后,仍旧运行,不停打印Yes,I am interruted,but I am still running

那么,如何正确中断?

既然是只能修改中断状态,那么我们应该针对中断状态做些什么。

public class InterruptionInJava implements Runnable{

    public static void main(String[] args) throws InterruptedException {

        Thread testThread = new Thread(new InterruptionInJava(),"InterruptionInJava");

        //start thread

        testThread.start();

//        Thread.sleep(1000);

        //interrupt thread

        testThread.interrupt();

        System.out.println("main end");

    }

    @Override

    public void run() {

        while(true){

            if(Thread.currentThread().isInterrupted()){

                System.out.println("Yes,I am interruted,but I am still running");

                return;

            }else{

                System.out.println("not yet interrupted");

            }

        }

    }

}

修改代码,在状态判断中如上,添加一个return就okay了。但现实中,我们可能需要做的更通用,不禁又要发出天问,如何中断线程?答案是添加一个开关

public class InterruptionInJava implements Runnable{

    private volatile static boolean on = false;

    public static void main(String[] args) throws InterruptedException {

        Thread testThread = new Thread(new InterruptionInJava(),"InterruptionInJava");

        //start thread

        testThread.start();

        Thread.sleep(1000);

        InterruptionInJava.on = true;

        System.out.println("main end");

    }

    @Override

    public void run() {

        while(!on){

            if(Thread.currentThread().isInterrupted()){

                System.out.println("Yes,I am interruted,but I am still running");

            }else{

                System.out.println("not yet interrupted");

            }

        }

    }

}

会输出类似结果,这表明是成功中断了的:

intersect在java中的用法 java的interrupt_System

这种开关的方式看起来包治百病,但是当遇到线程阻塞时,就会很无奈了,正如下面代码所示:

public class InterruptionInJava implements Runnable{

    private volatile static boolean on = false;

    public static void main(String[] args) throws InterruptedException {

        Thread testThread = new Thread(new InterruptionInJava(),"InterruptionInJava");

        //start thread

        testThread.start();

        Thread.sleep(1000);

        InterruptionInJava.on = true;

        System.out.println("main end");

    }

    @Override

    public void run() {

        while(!on){

            try {

                Thread.sleep(10000000);

            } catch (InterruptedException e) {

                System.out.println("caught exception: "+e);

            }

        }

    }

}

线程被阻塞无法被中断。这时候救世主interrupt函数又回来了,它可以迅速中断被阻塞的线程,抛出一个InterruptedException,把线程从阻塞状态中解救出来,show the code。

public class InterruptionInJava implements Runnable{

    private volatile static boolean on = false;

    public static void main(String[] args) throws InterruptedException {

        Thread testThread = new Thread(new InterruptionInJava(),"InterruptionInJava");

        //start thread

        testThread.start();

        Thread.sleep(1000);

        InterruptionInJava.on = true;

        testThread.interrupt();

        System.out.println("main end");

    }

    @Override

    public void run() {

        while(!on){

            try {

                Thread.sleep(10000000);

            } catch (InterruptedException e) {

                System.out.println("caught exception right now: "+e);

            }

        }

    }

}

结果截图,达到预期。

intersect在java中的用法 java的interrupt_测试工具_02

这种情形同样适用io阻塞,通常io阻塞会立即抛出一个SocketException,类似于上面说的InterruptedException。