关于java:我怎么能杀死一个线程?

How can I kill a thread? without using stop();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Thread currentThread=Thread.currentThread();
        public void run()
        {              

             while(!shutdown)
            {                              
                try
                {
                    System.out.println(currentThread.isAlive());
                Thread.interrupted();

                System.out.println(currentThread.isAlive());
                if(currentThread.isAlive()==false)
                {
                    shutdown=true;
                }
                }
                catch(Exception e)
                {
                    currentThread.interrupt();
                }                  
            }
        }

    });
    thread.start();


调用stop的另一种方法是使用interrupt向线程发出信号,您希望它完成正在执行的操作。(这假定您要停止的线程行为良好,如果它忽略了InterruptedExceptions,在抛出后立即吃掉它们,并且不检查中断状态,那么您将返回到使用Stop()的状态)。

下面是我为一个线程问题编写的一些代码,它是线程中断如何工作的一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class HelloWorld {

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

            public void run() {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        Thread.sleep(5000);
                        System.out.println("Hello World!");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
        System.out.println("press enter to quit");
        System.in.read();
        thread.interrupt();
    }
}

需要注意的一些事情:

  • 中断会导致sleep()wait()立即抛出,否则你会被困在等待睡眠时间过去。

  • 请注意,不需要单独的布尔标记。

  • 被停止的线程通过检查中断状态和捕获while循环之外的interruptedExceptions(使用它退出循环)进行协作。中断是一个可以使用异常进行流控制的地方,这就是它的全部意义。

  • 在catch块中的当前线程上设置中断在技术上是最好的做法,但对于本例来说,这是多余的,因为没有其他任何东西需要设置中断标志。

关于已发布代码的一些观察:

  • 发布的示例不完整,但将对当前线程的引用放入实例变量中似乎是一个坏主意。它将被初始化为创建对象的任何线程,而不是执行run方法的线程。如果在多个线程上执行同一个可运行实例,那么实例变量在大多数情况下不会反映正确的线程。

  • 检查线程是否处于活动状态必然会导致"真"(除非当前线程实例变量引用错误的线程时出现错误),只有在线程执行完毕后,Thread#isAlive才为"假",不会因为线程被中断而返回"假"。

  • 调用Thread#interrupted将导致清除中断标志,在这里没有意义,特别是因为返回值被丢弃。调用Thread#interrupted的目的是测试中断标志的状态,然后清除它,这是一种方便的方法,用于抛出InterruptedException的对象。


通常,线程在中断时终止。那么,为什么不使用本机布尔值呢?尝试isInterrupted():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   Thread t = new Thread(new Runnable(){
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                // do stuff        
            }  
        }});
    t.start();

    // Sleep a second, and then interrupt
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {}
    t.interrupt();


最好的方法是使用一个布尔标志来向线程发送信号。

1
2
3
4
5
6
7
8
9
10
11
class MyRunnable implements Runnable {

    public volatile boolean stopThread = false;

    public void run() {
            while(!stopThread) {
                    // Thread code here
            }
    }

}

创建一个名为myUnnable的myUnnable实例,将其包装在新的Thread实例中并启动该实例。如果要将线程标记为停止,请将myUnnable.StopThread设置为true。这样,它就不会停在某个东西的中间,只会停在我们期望它停下来的地方。