Java结束线程的三种方法

线程属于一次性消耗品,在执行完run()方法以后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能从新创建新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其余的须要循环处理的任务。在这种状况下,通常是将这些任务放在一个循环中,如while循环。当须要结束线程时,如何退出线程呢?java

有三种方法能够结束线程:web

  • 1.设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止安全

  • 2.使用interrupt()方法中断线程socket

  • 3.使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)svg

前两种方法均可以实现线程的正常退出;第3种方法至关于电脑断电关机同样,是不安全的方法。函数

1.使用退出标志终止线程
通常run()方法执行完,线程就会正常结束,然而,经常有些线程是伺服线程。它们须要长时间的运行,只有在外部某些条件知足的状况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并经过设置这个标志为true或false来控制while循环是否退出,代码示例:spa

public class ThreadSafe extends Thread {
    public volatile boolean exit = false; 
        public void run() { 
        while (!exit){
            //do something
        }
    } 
}

定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.线程

2.使用interrupt()方法中断当前线程
使用interrupt()方法来中断线程有两种状况:code

1.线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,经过代码捕获该异常,而后break跳出循环状态,从而让咱们有机会结束这个线程的执行。一般不少人认为只要调用interrupt方法线程就会结束,其实是错的, 必定要先捕获InterruptedException异常以后经过break来跳出循环,才能正常结束run方法。xml

代码示例:

public class ThreadSafe extends Thread {
    public void run() { 
        while (true){
            try{
                    Thread.sleep(5*1000);//阻塞5妙
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;//捕获到异常以后,执行break跳出循环。
                }
        }
    } 
}

2.线程未处于阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是同样的道理。
代码示例:

public class ThreadSafe extends Thread {
    public void run() { 
        while (!isInterrupted()){
            //do something, but no throw InterruptedException
        }
    } 
}

为何要区分进入阻塞状态和和非阻塞状态两种状况了,是由于当阻塞状态时,若是有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完以后会复位中断状态为false,因此异常抛出以后经过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,所以在线程未进入阻塞的代码段时是能够经过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要经过捕获异常来退出循环。所以使用interrupt()来退出线程的最好的方式应该是两种状况都要考虑:

代码示例:

public class ThreadSafe extends Thread {
    public void run() { 
        while (!isInterrupted()){ //非阻塞过程当中经过判断中断标志来退出
            try{
                Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
            }catch(InterruptedException e){
                e.printStackTrace();
                break;//捕获到异常以后,执行break跳出循环。
            }
        }
    } 
}

3.使用stop方法终止线程 程序中能够直接使用thread.stop()来强行终止线程,可是stop方法是很危险的,就象忽然关闭计算机电源,而不是按正常程序关机同样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用以后,建立子线程的线程就会抛出ThreadDeatherror的错误,而且会释放子线程所持有的全部锁。通常任何进行加锁的代码块,都是为了保护数据的一致性,若是在调用thread.stop()后致使了该线程所持有的全部锁的忽然释放(不可控制),那么被保护数据就有可能呈现不一致性,其余线程在使用这些被破坏的数据时,有可能致使一些很奇怪的应用程序错误。所以,并不推荐使用stop方法来终止线程。