并发编程陷阱系列 (二)InterruptException无处不在
程序员文章站
2022-03-02 08:48:17
...
当一个方法抛出 InterruptedException
时,它是在告诉您,如果执行该方法的线程被中断,它将尝试停止它正在做的事情而提前返回,并通过抛出 InterruptedException
表明它提前返回。
一旦你catch了中断异常,默认你就会处理它,所以JVM会清除中断状态,以防止方法退出后上层调用代码再处理一次异常。如果你只是简单地catch住,并不打算处理,那么就需要恢复被清除的中断位,让上层知晓,所以需要调用interrupt()
切忌生吞InterruptedException
异常,正确的做法:
1、将异常传递给调用方。
public class TaskQueue { private static final int MAX_TASKS = 1000; private BlockingQueue<Task> queue = new LinkedBlockingQueue<Task>(MAX_TASKS); public void putTask(Task r) throws InterruptedException { queue.put(r); } public Task getTask() throws InterruptedException { return queue.take(); } }
2、在重新抛出 InterruptedException 之前执行特定于任务的清理工作。
public class PlayerMatcher { private PlayerSource players; public PlayerMatcher(PlayerSource players) { this.players = players; } public void matchPlayers() throws InterruptedException { try { Player playerOne, playerTwo; while (true) { playerOne = playerTwo = null; // Wait for two players to arrive and start a new game playerOne = players.waitForPlayer(); // could throw IE playerTwo = players.waitForPlayer(); // could throw IE startNewGame(playerOne, playerTwo); } } catch (InterruptedException e) { // If we got one player and were interrupted, put that player back if (playerOne != null) players.addFirst(playerOne); // Then propagate the exception throw e; } } }3、捕捉 InterruptedException 后恢复中断状态
例如当由 Runnable 定义的任务调用一个可中断的方法时,就是如此。在这种情况下,不能重新抛出 InterruptedException,但是您也不想什么都不做。当一个阻塞方法检测到中断并抛出 InterruptedException 时,它清除中断状态。如果捕捉到 InterruptedException 但是不能重新抛出它,那么应该保留中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应。该任务可以通过调用 interrupt() 以 “重新中断” 当前线程来完成。
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) { // Restore the interrupted status Thread.currentThread().interrupt(); } } }参考: http://www.ibm.com/developerworks/cn/java/j-jtp05236.html
推荐阅读
-
java并发编程系列 ---(二)java 内存模型解析(JMM)
-
并发编程陷阱系列(五)double check
-
并发编程陷阱系列(八)不要吞食CountDownLatch的线程异常
-
并发编程陷阱系列(六)高并发环境下使用性能较低的Map
-
并发编程陷阱系列(四)volatile与变量脏读
-
并发编程陷阱系列(三)使用Thread.interrupt()中断线程
-
并发编程陷阱系列 (二)InterruptException无处不在
-
并发编程陷阱系列(七)读多写少使用synchronized导致性能下降
-
并发编程陷阱系列 (一)同步不完全
-
并发编程陷阱系列(七)读多写少使用synchronized导致性能下降