IBM开发者论坛2006年写的一篇关于InterruptedException的最佳实践,还是很不错的。
方式1:把中断异常InterruptedException抛给调用者来处理,比如说:
public Task getTask() throws InterruptedException {
return queue.take();
}
方式2:在中断异常抛出前,可以做一些保存数据的操作:
public class PlayerMatcher {
private PlayerSource players;
public PlayerMatcher(PlayerSource players) {
this.players = players;
}
public void matchPlayers() <strong>throws InterruptedException</strong> {
Player playerOne, playerTwo;
try {
while (true) {
playerOne = playerTwo = null;
// Wait for two players to arrive and start a new game
playerOne = players.waitForPlayer(); // 有可能会抛出中断异常
playerTwo = players.waitForPlayer(); // 有可能会抛出中断异常
startNewGame(playerOne, playerTwo);
}
}
catch (InterruptedException e) {
if (playerOne != null) // 把已经连接上的玩家1保存下来
players.addFirst(playerOne);
throw e; // 抛出异常
}
}
}
代码中是两个游戏玩家的线程必须同时到达,才能开始游戏,如果在玩家1已经连接上,玩家2发生了中断异常了,此时在抛出中断异常前,可以将已经连接上的玩家保存下来。
方式3:不要忽略中断异常,每次发生中断异常后,会清除当前线程的中断状态。可以在中断异常的catch块中重新设置中断状态。
public class TaskRunner implements Runnable {
private BlockingQueue<Task> queue;
public TaskRunner(BlockingQueue<Task> queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// 恢复中断状态
Thread.currentThread().interrupt();
}
}
}
可以看一下Thread的interrupt()方法,只是重新设置为中断状态:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
方式4:设计为可以取消任务的方式,当取消任务时抛出中断异常,任务捕获到异常后,终止执行任务。
public class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
}
方式5:设计为一个不可中断的任务,也就是即使发生中断了,还得让任务继续执行下去。
public Task getNextTask(BlockingQueue<Task> queue) {
boolean interrupted = false;
try {
while (true) {
try {
return queue.take();
} catch (InterruptedException e) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted)
Thread.currentThread().interrupt();
}
}