这里我们先来讲一下已经被弃用的 stop() 以及 suspend() 这两个方法
stop()
反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记线程的stop方法,以后我们再也不要说“停止线程”了。而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。
suspend()
suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。
执行线程如何获得自己的中断标志
1、Thread.currentThread.isInterrupted() 获取当前线程的中断标志
2、Thread.interrupted () 获取并重置中断标记值,并会将标记值重新设置为 false;
如何设置另外一个线程的中断标志
执行线程调用一个线程的 Interrupt() 将目标线程的中断标志设置为 true.
如何设置一个进程让其响应中断停止下来
第一种方式:
通过上面的知识点我们可以知道通过设置另外一个线程的中断标志更改为true 就能够将其进行终止下来,案例如下
private BlockingQueue<Runnable> chanel;
class WorkerTherad extends Thread{
@Override
public void run(){
Runnable task = null;
try {
for (;;){
try {
task = chanel.take();
} catch (Throwable e) {
e.printStackTrace();
}
}
}catch (InterruptedException e){
}
}
}
乍一看这个貌似乎好像也是可以响应中断 然后停止线程的运行的,但是还有一点情况是,当线程正在执行器内部可以抛出异常的步骤当中,我们外部线程所发过去的中断命令会被其捕获,然后并不会中断我们的线程,线程依然执行着。从这里可以看出我们的中断指令被“吞没”;我们可以看第二种方式对其进行一个缓和解决。
第二种方式:使用 interrupt() 方法 + 外加一个中断变量
public volatile boolean inUse = true;
private BlockingQueue<Runnable> chanel;
public WorkerTherad workerTherad = new WorkerTherad();
public void shutdown(){
inUse =false;
final Thread t = workerTherad;
if (null!=t){
t.interrupt();
}
}
class WorkerTherad extends Thread{
@Override
public void run(){
Runnable task = null;
try {
for (;;){
if (!inUse&&chanel.isEmpty()){
break;
}
try {
task = chanel.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}catch (InterruptedException e){
}
}
}
通过 外加一个中断标志变量,尽管我们的中断指令被吞噬,但是我们的目标线程还是依然有退路的,他能通过对线程停止标志的判断而进行停止。