java线程如何中断?Thread interrupt没有想象那么简单?

引子

本来以为interrupt()后,线程就立刻停止了,其实不是这样的!!!

interrupt()通知线程应该停止

interrupt()是Thread的实例方法,它通过设置线程中断状态,来提示线程应该停止,真正是否停止何时停止取决于程序员;interrupt()时,如果线程在WAITING/TIMED_WAITING状态(执行了wait()、wait(long)、join()、join(long)、sleep(long))则会清除中断状态,抛出InterruptedException,注不要使用stop来中止线程,此方法已不推荐使用,并会带来状态一致性问题。

interrupt()改变状态

Thread a = new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                while(true){

                    System.out.println(Thread.currentThread().isInterrupted()+"--"+(++i));
                }
            }
        });
        a.start();
        a.interrupt();
        System.out.println("线程被中断了");
线程被中断了
true--1
true--2
true--3
true--4
true--5
true--6
true--7
...

可以看到,执行了interrupt()后,线程为中断状态,但线程未停止。
一般的,如果接到线程终止,应该停止,如下


                while(true){
                    if(Thread.currentThread().isInterrupted()){  // 通过判断中止状态来采取操作
                        break;
                    }
                    System.out.println(Thread.currentThread().isInterrupted()+"--"+(++i));
                }
        

输出结果,没有输出数字

线程被中断了

waiting/timed_waiting状态,interrupt()线程抛出异常

线程处在waiting/timed_waiting状态,interrupt()导致目标线程抛出InterruptedException异常,并清除中断状态;

Thread a = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getState()+"-begin-"+Thread.currentThread().isInterrupted()); // 1
                try {
                    Thread.sleep(2000); //7
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getState()+"-end-"+Thread.currentThread().isInterrupted()); //2
                    e.printStackTrace(System.out);
                }
            }
        });
        a.start(); //3
        System.out.println(a.getState()+"--"+a.isInterrupted()); //4
        a.interrupt(); //5
        System.out.println(a.getState()+"--"+a.isInterrupted()); //6

输出结果有好几种情况,这是因为多线程交替执行导致,包括但不限于以下几种情况


这种情况的执行顺序是,345612


RUNNABLE--false  //
RUNNABLE--true
RUNNABLE-begin-true
RUNNABLE-end-false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at test.Test$1.run(Test.java:15)
	at java.lang.Thread.run(Thread.java:745)

这种情况的执行顺序是,341562

RUNNABLE--false
RUNNABLE-begin-false
RUNNABLE--true
RUNNABLE-end-false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at test.Test$1.run(Test.java:15)
	at java.lang.Thread.run(Thread.java:745)

这种情况的执行顺序是,317456,咱们重点解释这种情况,a.start()后,接着执行a线程run方法,1输出false,执行到7,进入timed_waiting状态,线程切换到主线程执行4,输出false,执行5后,线程中断状态为true,继续执行5,输出true,调度器切换到a线程抛出异常清除中断状态,执行2输出false。

RUNNABLE-begin-false
TIMED_WAITING--false
TIMED_WAITING--true
RUNNABLE-end-false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at test.Test$1.run(Test.java:15)
	at java.lang.Thread.run(Thread.java:745)

interrupt() vs isInterrupted() vs interrupted()

  • public void interrupt()
    • 设置线程状态,如果线程处在WAITING/TIMED_WAITING状态,则抛出InterruptedException,并清除中断状态;
  • public boolean isInterrupted()
    • 获取线程中断状态;
  • public static boolean interrupted()
    • 获取当前线程中断状态,然后清除中断状态,也就是说,如果连续执行两次,第二次为false
发布了336 篇原创文章 · 获赞 369 · 访问量 193万+

猜你喜欢

转载自blog.csdn.net/wangjun5159/article/details/103725946