多线程GCD 队列 异步 网络 socket block 循环引用

线程中断和终止

2016-09-12  本文已影响130人  mister_tao

线程中断的定义:(我的理解)就是中断不同于终止,终止是将处于阻塞状态的线程终止,清理资源.通常中断的线程不在执行状态,而是处于 sleep(),wait()等状态,线程中断方式 Thread.interrupt().


线程停止:不管线程是否在执行,强制停止,已有的过时方法 Thread.stop(),线程停止的方法目前最好的方式是用标记位.


一 ,首先介绍Thread.interrupt()方法:

Thread类包含interrupt()方法,因此你可以终止被阻塞的任务,这个方法将设置线程的中断状态,如果一个线程已经被阻塞,或者试图执行一个阻塞操作,那么设置这个线程的中断状态将抛出InterrupedException,当抛出该异常或者该任务调用Thread.interrupt()时,中断状态将被复位。正如你将看到的,Thread.interrupt()提供了离开run()循环而不抛出异常的第二种方式。

为了调用interrupt(),你必须持有Thread对象,新的concurrent类库为了避免直接对Thread对象的操作,尽量通过Executor来执行操作,如果你在Executor上调用shutdownNow(),那么将它将发送一个interrupt()调用给它启动的所有线程,这样会将所有阻塞的线程关闭掉.

另外一种情况是,如果只是想中断某个任务,使用Executor.submit()方法,就可以持有该任务的上下文,submit返回一个泛型Future<?>对象,通过该对象调用cancel()方法,那么实际上就调用了该线程的Thrad.interrupt()方法.


二, Executor中的shutdown()方法和shutdownNow()方法:

当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出.

根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。


三, 线程终止安全性较高的是设置标记位:

private  volatile boolean canceled = false;

public  void cancel(){

canceled = true;

}

@Override

public void run() {

while(!canceled){

while(true){System.out.println("# i : "+(i++)+", canceled : "+canceled);}

}

但是对于已经开始的任务,并不能马上停止,也就是说如果里面是个执行无限循环的任务,那么还是会一直执行下去,且这种停止的方式,并没有清理资源,节省资源. 线程执行完后会自动销毁,释放资源.

四, 线程Thread.stop方法的隐患

引用博客Java中的线程Thread方法之---stop()中的说法:调用Thread.stop()方法是不安全的,这是因为当调用Thread.stop()方法时,会发生下面两件事:

1. 即刻抛出ThreadDeath异常,在线程的run()方法内,任何一点都有可能抛出ThreadDeath Error,包括在catch或finally语句中。

2. 会释放该线程所持有的所有的锁,而这种释放是不可控制的,非预期的

会产生的不可控现象一:

当如果在给线程run方法中加同步锁, stop方法无法停止这个线程,原因是stop方法是同步的, 所以这两个方法持有同一个锁

现象二:当调用thread.stop()时,被停止的线程会不会释放其所持有的锁


上一篇下一篇

猜你喜欢

热点阅读