抛出InterruptedException,我犯了一个错误?
简而言之:
>一个阻塞方法应该包括throws InterruptedException,否则是一个普通的方法.
>阻塞方法可能会影响响应速度,因为可能难以预测何时完成这就是为什么需要抛出InterruptedException.
那是对的吗?
解决方法
您能够吸收这种中断的情况很少见.也许你正在计算一个迭代的解决方案,精度随着时间的推移而增加,但是当您的线程被中断时,您决定在规定的时间内达到的解决方案已经足够好了,并且仍然足以返回.换句话说,该解决方案仍然在您的方法范围内.
想像:
private double improveUpon(double start) throws InterruptedException { // ... } public double compute() { double result = 0.0; try { do { result = improveUpon(result); } while (couldBeImproved(result)); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } return result; }
或者,如果您只想遵守中断请求,则可以在不执行InterruptedException的情况下执行此操作:
private double improveUpon(double start) { // ... } public double compute() { final Thread current = Thread.currentThread(); double result = 0.0; do { result = improveUpon(result); } while (couldBeImproved(result) && !current.isInterrupted()); return result; }
对于另一个变体,请考虑您的方法必须完成其所有工作或向调用者指示无法完成它的情况,并且需要一段时间才能到达,但是您希望遵循线程中断.这样的事情就足够了
private double improveUpon(double start) { // ... } public double compute() throws InterruptedException { final Thread current = Thread.currentThread(); double result = 0.0; do { if (current.interrupted()) throw new InterruptedException(); result = improveUpon(result); } while (!isAdequate(result)); return result; }
请注意,我们调用Thread#interrup(),它具有清除线程的中断状态(如果已设置)的副作用.如果该方法返回true,那么我们作为调用者已经接受了保存和传达该中断状态的责任.在这种情况下,由于我们不假设我们创建了调用线程,我们没有足够的可见范围来了解它的中断策略,所以我们通过抛出InterruptedException来传达我们观察和采用的中断状态.
将方法标记为“阻塞”总是一个程度的问题;每个方法阻塞其呼叫者一段时间.您可能正在寻找的区别是方法是否阻止等待某些外部输入,例如用户按键或通过网络到达的消息.在这种情况下,您抛出InterruptedException的广告向您的呼叫者表明,您的方法可以安全地使用线程的呼叫者来控制其延迟.你在说,“这可能需要一段时间才能完成,但这不会比你愿意等待.”你在说,“我会跑,直到你告诉我不要.这与例如java.io.InputStream#read()
有所不同,即在三种情况发生之前就有可能阻止,否则呼叫者的线程不会被中断.
在大多数情况下,您的决定是为了回答以下问题:
>为了满足我的方法的要求,我需要调用抛出InterruptedException的任何方法吗?
>如果是这样,我已经完成了对我的呼叫者的任何使用的工作?
>如果没有,我也应该抛出InterruptedException.
>如果没有我调用throws InterruptedException,我应该尊重我的调用线程的中断状态?
>如果是这样,是否已经完成了任何工作,我发现我已经打扰了我的来电者的任何用途?
>如果没有,我应该抛出InterruptedException.
一个人检测到当前线程中断并吞下的情况通常仅限于您作者创建有问题的线程的情况,并且一旦线程中断,您就已经致力于退出线程的run()方法.这是“合作取消”的概念,您可以观察到您的线程停止运行的请求,并且您决定遵守该请求,尽快完成您的工作,并让线程的调用堆栈展开.再次,除非你是线程的run()方法的作者,否则你吞噬线程的中断状态可能会损害调用者和他们调用的其他方法的预期行为.
我建议你研究一个线程的中断状态的主题,并且使用方法Thread#isInterrupted()
,Thread#interrupted()
和Thread#interrupt()
.一旦理解了这些,并且看到正在运行的InterruptedException是Thread#isInterrupted()的替代表示返回true或者线程#interrup()的有礼貌的翻译已经返回true,这一切都应该开始变得更有意义了.
如果您需要更多的学习实例,请说出来,我可以在这里添加建议.