1.线程的自然终止
当某个线程的run()方法执行完毕,或者是抛出了一个未处理的异常,都会导致该线程自然终止。
2.调用某个线程对象的suspend()、resume() 和 stop()。
但这些方法因会产生一些不确定的问题如无法保证该线程的资源正常释放等等,以 suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。同样stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。正因为 suspend()、 resume()和 stop()方法带来的副作用,这些方法才被标注为不建议使用的过期方法。
3.interrupt(),isInterrupted(),interrupted()。
interrupt(),其他线程通过调用某个线程 A 的 interrupt()方法对其进行中断操作,本质上只是改变线程A的中断标志位由true改变成false,但是改变A的中断标志位不代表线程A一定会立即停止自己的工作,如果A中没有检查中断标志位是否为true并作出相应的处理,即A 线程完没有理会这种中断请求。则其他线程调用线程A的interrupt()对线程A是毫无影响的。然而java里的线程是协作式的,而非抢占式的。正常情况下开发者会根据具体的业务需求下会通过对线程A检查自身的中断标志位是否被置为true来进行响应,以此完成多线程之间的协调工作用以来高效的实现自身的业务需求。
isInterrupted(),Thread.interrupted(),线程通过方法 isInterrupted()来进行判断是否被中断,也可以调用静态方法 Thread.interrupted()来进行判断当前线程是否被中断,不过 Thread.interrupted() 会同时将中断标识位改写为 false。需要注意的是如果一个线程处于了阻塞状态(如线程调用了thread.sleep()、thread.join()、 thread.wait() 等),此时如果其他线程调用了该线程对象的interrupt()时,不仅不会将中断标志位改为true,同时会抛出 InterruptedException 中断异常,如果确实需要中断线程,则需要在异常代码块中再次调用interrupt()方法即可。
代码示例如下:
/***类说明:演示实现接口Runnable的线程如何中断*/
public class EndRunnable {private static class UseRunnable implements Runnable{@Overridepublic void run() {while(!Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName()+ "Runnable");}System.out.println(Thread.currentThread().getName()+" flag is "+Thread.currentThread().isInterrupted());}}public static void main(String[] args) throws InterruptedException {UseRunnable useRunnable = new UseRunnable();Thread endThread = new Thread(useRunnable,"endThread");endThread.start();Thread.sleep(20);endThread.interrupt();}}
/***类说明:演示继承Thread类的线程如何安全中断线程*/
public class EndThread {private static class UseThread extends Thread{public UseThread(String name) {super(name);}@Overridepublic void run() {String threadName = Thread.currentThread().getName();System.out.println(threadName+" flag ="+isInterrupted());while(!isInterrupted()){System.out.println(threadName+" is running");System.out.println(threadName+"inner interrrupt flag ="+isInterrupted());}System.out.println(threadName+" flag ="+isInterrupted());}}public static void main(String[] args) throws InterruptedException {Thread endThread = new UseThread("endThread");endThread.start();Thread.sleep(20);endThread.interrupt();//中断线程,其实是设置线程的标识位true}
/***类说明:阻塞方法中抛出InterruptedException异常后,如果需要继续中断,需要手动再中断一次*/ public class HasInterrputException {private static class UseThread extends Thread{public UseThread(String name) {super(name);}@Overridepublic void run() {while(!isInterrupted()) {try {Thread.sleep(100);} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+" in InterruptedException interrupt flag is "+isInterrupted()); //线程在阻塞情况下被中断会抛出异常,如果确实需要中断该线程需在异常代码块里再次调用interrupt()中断方法interrupt();e.printStackTrace();}System.out.println(Thread.currentThread().getName()+ " Thread.");}System.out.println(Thread.currentThread().getName()+" flag is "+isInterrupted());}}public static void main(String[] args) throws InterruptedException {Thread endThread = new UseThread("HasInterrputEx");endThread.start();Thread.sleep(500);endThread.interrupt();} }