一、停止线程的方法

1、使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
2、使用stop方法强行终止线程,此方法作废过期,不推荐使用,因为可能会产生不可预料的结果。
3、使用interrupt方法中断线程。

二、interrupt方法

调用intertupt方法仅仅是在当前线程中打一个停止的标记,并不是真正的停止线程。

三、判断线程是否停止

3.1、判断方法

interrupted():测试当前线程Thread对象是否已经是终端状态,执行后具有将状态标志清楚为false的功能。
isInterrupted():测试线程Thread对象是否已经是中断状态,但不清楚状态标志

3.2、中断说明

1、如果线程不处于阻塞状态,那么调用interrupt()方法仅仅是将[中断标志位]将被置为true
2、如果当前线程处于blocked阻塞(因为调用wait、sleep和join造成的)状态时被interrupt了,那么[中断标志位]将被清除,也就是设置为false,并且收到一个InterruptedException异常。
3、如果当前线程处于blocked阻塞(因为NIO的InterruptibleChannel进行的I/O操作造成的)状态时被interrupt了,则会关闭channel,[中断标志位]将会被置为true,并且当前线程会收到一个ClosedByInterruptException异常。
4、如果当前线程处于blocked阻塞(因为NIO的Selector造成的)状态时被interrupt了,那么[中断标志位]将被置为true,然后当前线程会立即从选择器区域返回并返回值(可能为非零的值)。

需要说明的是:interrupt()方法并不是中断线程,而是中断阻塞状态,也就是将线程的[中断标志位]置为true。中断后线程将继续执行。
PS:事实上,interrupt方法只是改变目标线程的中断状态(interrupt status),而那些会抛出InterruptedException异常的方法,如wait、sleep、join等,都是在方法内部不断地检查中断状态的值。

3.3、几个中断方法对比:

  • public static boolean interrupted():测试当前线程(这边要注意的是这个方法返回的是当前正在执行的线程的中断状态,注意和isInterrupted的区别)是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。
  • public boolean isInterrupted():测试线程是否已经中断。线程的中断状态 不受该方法的影响,也就是说不清除中断标志。
  • public void interrupt():中断线程,例如,当线程A运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为true并立即返回。设置标志仅仅是设置标志,线程A实际并没有被中断,它会继续往下执行。如果线程A因为调用了wait系列函数、join方法或者sleep方法而被阻塞挂起,这时候若线程B调用线程A的interrupt()方法,线程A会在调用这些方法的地方抛出InterruptedException异常而返回。

当线程为了等待一些特定条件的到来时,一般会调用sleep函数、wait系列函数或者join()函数来阻塞挂起当前线程。比如一个线程调用了Thread. sleep(3000),那么调用线程会被阻塞,直到3s后才会从阻塞状态变为激活状态。但是有可能在3s内条件已被满足,如果一直等到3s后再返回有点浪费时间,这时候可以调用该线程的interrupt()方法,强制sleep方法抛出InterruptedException异常而返回,线程恢复到激活状态。

三、能停止的线程——异常法

四、在沉睡中停止

五、暴力停止

1、stop
2、stop与ThreadDeath异常
3、stop释放锁后的不良后果

六、return停止线程

七、暂停线程

1、suspend/resume
suspend()方法暂停线程
resume()方法恢复线程

2、suspend与resume的缺点——独占
3、suspend与resume的缺点——不同步

八、中断总结