Java没有提供任何机制来安全的终止线程,但是提供了中断机制,能够使一个线程安全的终止另一个线程的工作。
1、任务取消
不使用中断,设置一个标识,任务定期查看标识,如果标识为true,则任务结束。但是存在一个问题,如果使用这种办法,调用了一个阻塞任务,那么任务永远也不可能检查这个标识,因此任务永远不会结束。
2、中断
Thread类中包含了中断线程以及查询线程是否中断的方法。
public class Thread{
public void interrupt(){}
public boolean isInterrupt(){}
public static boolean interrupted(){}
}
一些特殊的阻塞库的方法支持中断,例如Thread.sleep和Object.wait方法,这些方法会检查线程何时中断,并在发现中断时返回。具体来说是:1清除中断状态。2抛出InterruptedException异常。中断只是发送一个请求中断的消息,然后由线程在下一个合适的时候中断自己。
2.1 响应中断
1、传递中断
public Task getNextTask() throw InterruptedException{
return quene.take();
}
2、恢复中断状态。
一些在执行的任务无法中断,但是你依然需要保存中断状态,当任务结束后,中断线程。
public Task getNextTask(***){
boolean interrupted =false;
try{
while(true){
try{
return quene.take();
}catch(InterruptedException e){
interruped =true;
//重新尝试
}
}
}finally{
if(interrupted){
Thread.currentThread().interrupt();
}
}
}
3、使用Future来取消
Future.cancel();
public static void timeRun(Runnable r,long timeout,TimeUnit unit)throw InterruptedExeception{
try{
task.get(timeout,unit);
}catch(TimeoutException e){
//接下来任务将被取消
}catch(InterruptedExeception e){
//如果在任务中抛出了异常,那么重新抛出此异常
throw launderThrowable(e.getCause());
}finally{
//如果任务已经结束,那么取消操作不会造成影响。
//如果正在运行,则中断
task.cancel(true);
}
}
4、处理不可中断的阻塞
未完待续..........
3、停止基于线程的服务
在ExecutorService中提供了shutdown和shutdownNow方法
shutdown:
- 停止接收外部submit的任务
- 内部正在跑的任务和队列里等待的任务,会执行完
- 等到第二步完成后,才真正停止
shutdownNow:
- 跟shutdown()一样,先停止接收外部提交的任务
- 忽略队列里等待的任务
- 尝试将正在跑的任务
interrupt
中断 - 返回返回所有已提交但尚未开始的任务,从而将这些任务写入日志或者保存起来以便之后进行处理。