使用状态变量来终结任务
有时我们可以使用一个状态变量(如布尔值)来终结任务的执行,这种方式非常平和,且提供给你机会在任务终止前做一些操作。如:
public class StateStopTask implements Runnable{
private static volatile boolean isCancled = false;
public void run() {
while(true) {
if(isCancled == true) {
System.out.println("StateStopTask is stop");
return;
}
}
}
public static void main(String []args) {
new Thread(new StateStopThread()).start();
Thread.sleep(3000);
isCancled = true;
}
}
或者直接使用Thread.interrupt()来设置线程的中断标识,并且在程序中检测该标识,可以避免状态变量的定义。
public class StateStopTask implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted()) {
System.out.println("StateStopTask is running");
}
System.out.println("StateStopTask is stopping");
}
public static void main(String []args) {
Thread t = new Thread(new StateStopThread()).start();
Thread.sleep(3000);
t.interrupt();
}
}
在阻塞时终结
前面使用状态变量只能在线程运行到该检测时才能终止,有时我们需要线程无论在何时何地都能够被终止,尤其是在阻塞的时候。一个任务进入阻塞状态,可能有如下原因:
- 通过调用sleep(milliseconds)使任务进入休眠状态,在这种情况下,任务在指定的时间内不会运行。
- 你可以通过wait()使线程挂起。直到线程得到了notify()或notifyAll()消息(或者在JavaSE5的java.util.concurrent类库中等价的signal()或signalAll()消息),线程才会进入就绪状态。
- 任务在等待某个输入输出完成。
- 任务试图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁。
中断
程序在由于sleep或者wait()导致的阻塞情况下,如果被调用interrupt()方法将抛出interruptedExcetion异常,并且中断状态将清除。程序在由于IO和锁的阻塞时,调用interrupt()方法不会抛出interruptedException,但会设置中断状态。使用interrupted()可以检测中断状态并且如果正处于中断则清除中断状态,所以在程序中一般使用下面的方式检测中断,并做善后处理:
public class InterruptedTask implements Runnable{
public void run() {
while(!Thread.currentThread().interrupted()) {
try {
System.out.println("InterruptedTask running");
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("interrupted by InterruptedException ")
}
}
System.out.println("InterruptedTask Interrupted")
}
}
现代java代码不推荐直接操作Thread对象,转而尽量通过Executor来执行所有操作。如果你在Executor上调用shutdownNow(),那么它将发送一个interrupt()调用给它启动的所有线程。这样做是常见的,因为一个Executor通常执行同一类任务,所以经常会希望关闭Executor的所有任务。然后,你有时会希望只中断单一的任务。如果使用Executor,那么通过调用submit()而不是executor()来启动任务,就可以持有该任务的上下文,submit()将返回一个泛型Future<?>,其中有一个未修饰的参数,因为你不能调用get(),使用这个Futrue对象可以调用cancle(),如果传递true给cancle(),那么在这个线程上就会调用interrupt()方法。
一般由于锁而导致的阻塞无法中断,但原子锁(ReentrantLock)支持可中断的阻塞操作lockInterruptibly()。
漫谈并发编程(四):终结任务
原文:http://blog.csdn.net/troy__/article/details/40627701