如何中断线程in Java

时间:2022-01-09 18:38:08
如何中断Java线程?查看API,不就是用interrupt()方法么?而线程是否已经中断则用Thread.currentThread().isInterrupted()返回true/false: public class ThreadDemo extends Thread{
        public static void main(String[] args) throws InterruptedException {
                Thread thread = new ThreadDemo();
                thread.start();
                thread.sleep(100);
                thread.interrupt(); //中断线程
        }

        @Override
        public void run() {
                while(!Thread.currentThread().isInterrupted()) {
                        System.out.println("thread running");

                        try {
                                Thread.sleep(100);
                        }catch(InterruptedException e)
                        {
                                System.out.println("InterruptedException");
                        }
                }

                System.out.println("thread interrupted");
        }
}
运行结果:
thread running
InterruptedException
thread running
thread running
thread running
thread running
...
  很快发现这方法似乎有问题,线程没有成功中断,于是在处理InterruptedException异常后调用break跳出while循环: public class ThreadDemo extends Thread{
        public static void main(String[] args) throws InterruptedException {
                Thread thread = new ThreadDemo();
                thread.start();
                thread.sleep(100);
                thread.interrupt(); //中断线程
        }

        @Override
        public void run() {
                while(!Thread.currentThread().isInterrupted()) {
                        System.out.println("thread running");

                        try {
                                Thread.sleep(100);
                        }catch(InterruptedException e)
                        {
                                System.out.println("InterruptedException");
                                break;
                        }
                }

                System.out.println("thread interrupted");
        }
}
运行结果(线程成功中断):
thread running
InterruptedException
thread interrupted
  接着在网上搜索了一下,写了一些例子研究后明白如何写一个可中断的线程。
首先发现在调用线程的start()后,立即调用interrupt()中断线程,线程停止了――被挡在while条件的外面:
public class ThreadDemo extends Thread{
        public static void main(String[] args) throws InterruptedException {
                Thread thread = new ThreadDemo();
                thread.start();
                //thread.sleep(100);
                thread.interrupt(); //中断线程
        }

        @Override
        public void run() {
                System.out.println("in run()");
                while(!Thread.currentThread().isInterrupted()) {
                        System.out.println("thread running");

                        try {
                                Thread.sleep(100);
                        }catch(InterruptedException e)
                        {
                                System.out.println("InterruptedException");
                                //break;
                        }
                }

                System.out.println("thread interrupted");
        }
}
运行结果:
in run()
thread interrupted
  然后按照网上说的在异常处理时再次中断,原来这样就能成功地用interrupt方法中断线程: public class ThreadDemo extends Thread{
        public static void main(String[] args) throws InterruptedException {
                Thread thread = new ThreadDemo();
                thread.start();
                thread.sleep(100);
                thread.interrupt(); //中断线程
        }

        @Override
        public void run() {
                while(!Thread.currentThread().isInterrupted()) {
                        System.out.println("thread running");

                        try {
                                Thread.sleep(100);
                        }catch(InterruptedException e)
                        {
                                System.out.println("InterruptedException");
                                Thread.currentThread().interrupt(); //再次中断线程
                                //break;
                        }
                }

                System.out.println("thread interrupted");
        }
}
运行结果(线程成功中断):
thread running
InterruptedException
thread interrupted
  为什么在调用interrupt()前加上sleep(),导致的结果不同呢?
  我认为Thread对象只有在调用start()时才分配资源创建线程提供给CPU调度。而这过程需要时间,因为时间差,导致了在进入run()方法前,中断标志已经被set on,于是被挡在while条件上。
而再次中断线程,中断标志被set on了,然后循环回到while条件判断,于是退出循环。

而线程被中断后,该对象依然存在的,只是线程不能再次调用start()否则会报异常IllegalThreadStateException。 public class ThreadDemo extends Thread{
        public static void main(String[] args){
          try{
                 ThreadDemo thread = new ThreadDemo();
                 thread.start();
                 thread.sleep(100);

                 thread.interrupt(); //中断线程
                 thread.sleep(100);

                 thread.printStr();
                 thread.interrupt(); //第三次中断线程

                 thread.printStr();
                 thread.join();
          }catch(InterruptedException e){
            e.printStackTrace();
          }
        }

        private void printStr(){
          System.out.println("thread obj");
        }

        @Override
        public void run() {
                while(!Thread.currentThread().isInterrupted()) {
                        System.out.println("thread running");

                        try {
                                Thread.sleep(100);
                        }catch(InterruptedException e)
                        {
                                System.out.println("InterruptedException");
                                Thread.currentThread().interrupt(); //再次中断线程
                        }
                }

                System.out.println("thread interrupted");
        }
}
运行结果:
thread running
InterruptedException
thread interrupted
thread obj
thread obj
  简单总结:
1. 线程start()后马上调用interrupt(),在进入run()时中断标志已经被set on;
2. 在处理sleep()可能抛出的InterruptedException时,再次中断线程即可成功中断;
3. 注意interrupt()方法是set on 中断标志的,interrupted()方法是判断后并清除中断标志的。
  isInterrupted()和interrputed()方法的区别
public static boolean interrupted()
    测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
  public boolean isInterrupted()
    测试线程是否已经中断。线程的中断状态不受该方法的影响。
  两者都是如果该线程已经中断,则返回 true;否则返回 false。     参考文章 《Java 可中断线程》 http://blog.csdn.net/sapphiron/archive/2008/10/05/3018053.aspx 此文介绍更多的处理其他阻塞情况的中断方法。