- 浏览: 141853 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
zoutm:
文章写得深入浅出,顶
我们为什么要关注MapReduce? -
gongmingwind:
写的不错
Cookie的格式及组成 -
yanite:
翻译的不全,而且把不该翻译的也译了,郁闷.
HTTP/1.1 RFC2616中文 -
RStallman:
哪一个兼容性最好?最快?前提是免费的。
总结Embedding Brower JAVA API -
jiangzhx:
你好,请问你找到不带GUI,可以渲染html的工具了吗,谢谢j ...
总结Embedding Brower JAVA API
Many Java™ language methods, such asThread.sleep()
andObject.wait()
, throwInterruptedException
. You can't ignore it because it's a checked exception, but what should you do with it? In this month's Java theory and practice, concurrency expert Brian Goetz explains what InterruptedException means, why it is thrown, and what you should do when you catch one.
<script type="text/javascript"></script>
This story is probably familiar: You're writing a test program and you need to pause for some amount of time, so you call Thread.sleep()
. But then the compiler or IDE balks that you haven't dealt with the checked InterruptedException
. What is InterruptedException
, and why do you have to deal with it?
The most common response to InterruptedException
is to swallow it -- catch it and do nothing (or perhaps log it, which isn't any better) -- as we'll see later in Listing 4. Unfortunately, this approach throws away important information about the fact that an interrupt occurred, which could compromise the application's ability to cancel activities or shut down in a timely manner.
When a method throws InterruptedException
, it is telling you several things in addition to the fact that it can throw a particular checked exception. It is telling you that it is a blocking method and that it will make an attempt to unblock and return early -- if you ask nicely.
A blocking method is different from an ordinary method that just takes a long time to run. The completion of an ordinary method is dependent only on how much work you've asked it to do and whether adequate computing resources (CPU cycles and memory) are available. The completion of a blocking method, on the other hand, is also dependent on some external event, such as timer expiration, I/O completion, or the action of another thread (releasing a lock, setting a flag, or placing a task on a work queue). Ordinary methods complete as soon as their work can be done, but blocking methods are less predictable because they depend on external events. Blocking methods can compromise responsiveness because it can be hard to predict when they will complete.
Because blocking methods can potentially take forever if the event they are waiting for never occurs, it is often useful for blocking operations to be cancelable. (It is often useful for long-running non-blocking methods to be cancelable as well.) A cancelable operation is one that can be externally moved to completion in advance of when it would ordinarily complete on its own. The interruption mechanism provided by Thread
and supported by Thread.sleep()
and Object.wait()
is a cancellation mechanism; it allows one thread to request that another thread stop what it is doing early. When a method throws InterruptedException
, it is telling you that if the thread executing the method is interrupted, it will make an attempt to stop what it is doing and return early and indicate its early return by throwing InterruptedException
. Well-behaved blocking library methods should be responsive to interruption and throw InterruptedException
so they can be used within cancelable activities without compromising responsiveness.
Every thread has a Boolean property associated with it that represents its interrupted status. The interrupted status is initially false; when a thread is interrupted by some other thread through a call to Thread.interrupt()
, one of two things happens. If that thread is executing a low-level interruptible blocking method like Thread.sleep()
, Thread.join()
, or Object.wait()
, it unblocks and throws InterruptedException
. Otherwise, interrupt()
merely sets the thread's interruption status. Code running in the interrupted thread can later poll the interrupted status to see if it has been requested to stop what it is doing; the interrupted status can be read with Thread.isInterrupted()
and can be read and cleared in a single operation with the poorly named Thread.interrupted()
.
Interruption is a cooperative mechanism. When one thread interrupts another, the interrupted thread does not necessarily stop what it is doing immediately. Instead, interruption is a way of politely asking another thread to stop what it is doing if it wants to, at its convenience. Some methods, like Thread.sleep()
, take this request seriously, but methods are not required to pay attention to interruption. Methods that do not block but that still may take a long time to execute can respect requests for interruption by polling the interrupted status and return early if interrupted. You are free to ignore an interruption request, but doing so may compromise responsiveness.
One of the benefits of the cooperative nature of interruption is that it provides more flexibility for safely constructing cancelable activities. We rarely want an activity to stop immediately; program data structures could be left in an inconsistent state if the activity were canceled mid-update. Interruption allows a cancelable activity to clean up any work in progress, restore invariants, notify other activities of the cancellation, and then terminate.
Dealing with InterruptedException
If throwing InterruptedException
means that a method is a blocking method, then calling a blocking method means that your method is a blocking method too, and you should have a strategy for dealing with InterruptedException
. Often the easiest strategy is to throw InterruptedException
yourself, as shown in the putTask()
and getTask()
methods in Listing 1. Doing so makes your method responsive to interruption as well and often requires nothing more than adding InterruptedException
to your throws clause.
Listing 1. Propagating InterruptedException to callers by not catching it
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(); } } |
Sometimes it is necessary to do some amount of cleanup before propagating the exception. In this case, you can catch InterruptedException
, perform the cleanup, and then rethrow the exception. Listing 2, a mechanism for matching players in an online game service, illustrates this technique. The matchPlayers()
method waits for two players to arrive and then starts a new game. If it is interrupted after one player has arrived but before the second player arrives, it puts that player back on the queue before rethrowing the InterruptedException
, so that the player's request to play is not lost.
Listing 2. Performing task-specific cleanup before rethrowing InterruptedException
public class PlayerMatcher { private PlayerSource players; public PlayerMatcher(PlayerSource players) { this.players = players; } public void matchPlayers() throws InterruptedException { Player playerOne, playerTwo; try { 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; } } } |
Sometimes throwing InterruptedException
is not an option, such as when a task defined by Runnable
calls an interruptible method. In this case, you can't rethrow InterruptedException
, but you also do not want to do nothing. When a blocking method detects interruption and throws InterruptedException
, it clears the interrupted status. If you catch InterruptedException
but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to. This task is accomplished by calling interrupt()
to "reinterrupt" the current thread, as shown in Listing 3. At the very least, whenever you catch InterruptedException
and don't rethrow it, reinterrupt the current thread before returning.
Listing 3. Restoring the interrupted status after catching InterruptedException
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();
}
}
}
|
The worst thing you can do with InterruptedException
is swallow it -- catch it and neither rethrow it nor reassert the thread's interrupted status. The standard approach to dealing with an exception you didn't plan for -- catch it and log it -- also counts as swallowing the interruption because code higher up on the call stack won't be able to find out about it. (Logging InterruptedException
is also just silly because by the time a human reads the log, it is too late to do anything about it.) Listing 4 shows the all-too-common pattern of swallowing an interrupt:
Listing 4. Swallowing an interrupt -- don't do this
// Don't do this 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 swallowed) { /* DON'T DO THIS - RESTORE THE INTERRUPTED STATUS INSTEAD */ } } } |
If you cannot rethrow InterruptedException
, whether or not you plan to act on the interrupt request, you still want to reinterrupt the current thread because a single interruption request may have multiple "recipients." The standard thread pool (ThreadPoolExecutor
) worker thread implementation is responsive to interruption, so interrupting a task running in a thread pool may have the effect of both canceling the task and notifying the execution thread that the thread pool is shutting down. If the task were to swallow the interrupt request, the worker thread might not learn that an interrupt was requested, which could delay the application or service shutdown.
|
Nothing in the language specification gives interruption any specific semantics, but in larger programs, it is difficult to maintain any semantics for interruption other than cancellation. Depending on the activity, a user could request cancellation through a GUI or through a network mechanism such as JMX or Web Services. It could also be requested by program logic. For example, a Web crawler might automatically shut itself down if it detects that the disk is full, or a parallel algorithm might start multiple threads to search different regions of the solution space and cancel them once one of them finds a solution.
Just because a task is cancelable does not mean it needs to respond to an interrupt request immediately. For tasks that execute code in a loop, it is common to check for interruption only once per loop iteration. Depending on how long the loop takes to execute, it could take some time before the task code notices the thread has been interrupted (either by polling the interrupted status with Thread.isInterrupted()
or by calling a blocking method). If the task needs to be more responsive, it can poll the interrupted status more frequently. Blocking methods usually poll the interrupted status immediately on entry, throwing InterruptedException
if it is set to improve responsiveness.
The one time it is acceptable to swallow an interrupt is when you know the thread is about to exit. This scenario only occurs when the class calling the interruptible method is part of a Thread
, not a Runnable
or general-purpose library code, as illustrated in Listing 5. It creates a thread that enumerates prime numbers until it is interrupted and allows the thread to exit upon interruption. The prime-seeking loop checks for interruption in two places: once by polling the isInterrupted()
method in the header of the while loop and once when it calls the blocking BlockingQueue.put()
method.
Listing 5. Interrupts can be swallowed if you know the thread is about to exit
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(); } } |
Not all blocking methods throw InterruptedException
. The input and output stream classes may block waiting for an I/O to complete, but they do not throw InterruptedException
, and they do not return early if they are interrupted. However, in the case of socket I/O, if a thread closes the socket, blocking I/O operations on that socket in other threads will complete early with a SocketException
. The nonblocking I/O classes in java.nio
also do not support interruptible I/O, but blocking operations can similarly be canceled by closing the channel or requesting a wakeup on the Selector
. Similarly, attempting to acquire an intrinsic lock (enter a synchronized
block) cannot be interrupted, but ReentrantLock
supports an interruptible acquisition mode.
Some tasks simply refuse to be interrupted, making them noncancelable. However, even noncancelable tasks should attempt to preserve the interrupted status in case code higher up on the call stack wants to act on the interruption after the noncancelable task completes. Listing 6 shows a method that waits on a blocking queue until an item is available, regardless of whether it is interrupted. To be a good citizen, it restores the interrupted status in a finally block after it is finished, so as not to deprive callers of the interruption request. (It can't restore the interrupted status earlier, as it would cause an infinite loop -- BlockingQueue.take()
could poll the interrupted status immediately on entry and throws InterruptedException
if it finds the interrupted status set.)
Listing 6. Noncancelable task that restores interrupted status before returning
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(); } } |
|
You can use the cooperative interruption mechanism provided by the Java platform to construct flexible cancellation policies. Activities can decide if they are cancelable or not, how responsive they want to be to interruption, and they can defer interruption to perform task-specific cleanup if returning immediately would compromise application integrity. Even if you want to completely ignore interruption in your code, make sure to restore the interrupted status if you catch InterruptedException
and do not rethrow it so that the code that calls it is not deprived of the knowledge that an interrupt occurred.
Learn
- Java 2 Platform API Specifications: API specifications for the Java 2 Platform, Standard Edition, version 1.4.2.
- Java Concurrency in Practice (Addison-Wesley Professional, Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, and Doug Lea, June 2006): Chapter 7 of this how-to manual for developing concurrent programs in the Java language addresses the details of interruption and cancellation in much greater depth.
- Java theory and practice: The complete series by Brian Goetz.
- The Java technology zone: Hundreds of articles about every aspect of Java programming.
Get products and technologies
- JDK 5.0 Update 6: Get the latest update of JDK 5.0.
- The IBM implementation of Java technology: Download the SDKs for AIX, Linux, and z/OS, among other IBM developer kits for Java technology, from this page.
Discuss
- Participate in the discussion forum.
- developerWorks blogs: Get involved in the developerWorks community.
|
Brian Goetz has been a professional software developer for over 18 years. He is a Principal Consultant at Quiotix, a software development and consulting firm located in Los Altos, California, and he serves on several JCP Expert Groups. Brian's book, Java Concurrency In Practice, will be published in May 2006 by Addison-Wesley. See Brian's published and upcoming articles in popular industry publications.
中文翻译:http://www.ibm.com/developerworks/cn/java/j-jtp05236.html |
发表评论
-
ant start stop tomcat
2009-05-30 11:55 2571<target name="tomca ... -
暂时存记录:spring乱码过滤器
2008-11-05 22:59 1537<filter> <filt ... -
编译Google浏览器
2008-09-09 09:51 2564Google一直传言要做自己的浏览器,上周 ... -
关于http的Last-Modified和ETag
2008-09-02 17:05 21211) 什么是”Last-Modifie ... -
Http的一些编码
2008-09-01 15:43 1938HTTP Headers The headers of a H ... -
分布式Web爬虫的设计
2008-08-20 11:55 3332URL管理服务器(URL-Server):负责url的集中管理 ... -
Java 5.0的多线程类或接口
2008-08-19 17:49 1118Executor ExecutorService Callab ... -
JDK5.0 Excutor创建线程池
2008-08-19 16:11 1893import java.util.concurrent.Exe ... -
Java正则表达式
2008-08-10 13:21 1354两个问题 a. 如何知道一个url是 ... -
Swing HTML显示组件
2008-07-17 10:33 6031Java Swing本身没有提供好的html显示组件,而且也不 ... -
总结Embedding Brower JAVA API
2008-07-10 11:32 3891总结一些找到的嵌入浏览器: WebRenderer 对 ... -
Cookie的格式及组成
2008-06-26 10:49 30205Cookie由变量名和值组 ... -
HTTP头信息
2008-06-25 16:24 1970HTTP的头域包括通用头,请求头,响应头和实体头四个部 ... -
HTTP Cookie & Session
2008-06-25 15:50 3790COOKIECOOKIE是大家都非常 ... -
HTTP 1.0 与 1.1比较
2008-06-25 14:32 5312一个WEB站点每天可能要接收到上百万的用户请求,为了提高系统 ... -
HTTP/1.1 RFC2616中文
2008-06-25 14:27 6604官方RFC2616文档: http://www ... -
Watij - Web Application Testing in Java
2008-05-29 16:54 2390发现一个抓取动态网页的好东东: Watij (pro ... -
Commons 命令行接口使用(未翻译)
2008-05-15 16:12 1401暂未翻译,链接主页http://commons.apache. ... -
Java局部线程变量---ThreadLocal
2008-05-15 16:02 6276ThreadLocal是什么 早在J ... -
Heritrix QueueAssignmentPolicy问题
2008-04-30 17:51 3792Re: [archive-crawler] Extend Qu ...
相关推荐
《图像处理:处理纹理》是图像处理领域内一部权威性的著作,由Maria Petrou和Pedro Garcia Sevilla两位学者共同编写,他们分别来自英国伦敦帝国理工学院和西班牙卡斯特利翁的Jaume I大学。该书由全球知名的学术出版...
### 多标签分类:通过合并标签处理不平衡问题 #### 摘要与介绍 本文讨论了一个在多标签分类(Multi-Label Classification, MLC)领域中的常见问题——数据不平衡,并提出了一种新颖的方法来解决这一难题。...
标题中的"ASTM E178 - 21"指的是美国材料与...通过阅读提供的"ASTM E178 - 21 Standard Practice for Dealing With Outlying Observations - 完整英文版(11页).pdf"文件,可以深入学习这一标准的细节和具体实施步骤。
Key Features Load, manipulate and analyze data from different sources ...Chapter 11: Dealing with Messy Data Chapter 12: Dealing with Large Data Chapter 13: Reproducibility and Best Practices
Dealing with backwards compatibility Generating level data Making iOS and Android web apps Taking your game offline Using Web Workers Persistent Game Data Drawing with Canvas Capturing player input ...
在进行数据包络分析(Data Envelopment Analysis, DEA)研究时,经常需要面对的问题之一是如何处理非期望产出(undesirable outputs)。传统DEA模型在处理生产效率分析时通常假设决策单元(Decision Making Units, ...
标题与描述均提到“Hadoop权威”,这表明文章或资源主要聚焦于Hadoop技术的深入讲解与权威解读。Hadoop是一种开源软件框架,用于分布式存储和处理大型数据集。它由Apache基金会维护,广泛应用于大数据处理领域。...
113⁄4 A Little Bit of Threading: Dealing with Waiting 461 12 Advanced Iteration: Looping like Crazy 477 A Installing: Installing Python 521 B Pythonanywhere: Deploying Your Webapp 529 C Top Ten ...
Leadership coaching has become vitally important to today?... Packed with cutting-edge ideas and proven best practices, this is the definitive source of information for anyone dealing with coaching.
Table of Contents: PART 1 - DOCKER FUNDAMENTALS Chapter 1 Discovering Docker Chapter 2 Understanding Docker: Inside The Engine Room ...Chapter 3 Docker In Production: Dealing With Challenges
Dealing with Errors 552 Catching Exceptions 559 Tips for Using Exceptions 568 Using Assertions 571 Logging 575 Debugging Tips 591 Using a Debugger 607 Chapter 12: Generic Programming 613 ...
这篇PPT课件是针对八年级英语教学的内容,主题为“应对困难”(Dealing with trouble)。通过一系列的填空练习和情景模拟,旨在帮助学生掌握如何在不同情况下正确处理问题,尤其是面对紧急情况时的应对策略。以下是...
■■Chapter 7: Dealing with Relationships Partial Updates and Other Complexities 157 ■■Chapter 8: Supporting Diverse Clients 209 ■■Chapter 9: Completing the Picture 221 Index ">About the Authors ...