在停止线程时抛出InterruptedException是否必不可少?我可以使用其他异常类型吗? [英] Is throwing InterruptedException essential when stopping threads? Can I use another exception type?

查看:86
本文介绍了在停止线程时抛出InterruptedException是否必不可少?我可以使用其他异常类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有比赛代码,用于学生代码.因此,我无法控制学生的密码.

I have tournament code for students' codes. Therefore I have no control over the students' codes.

我需要为学生的代码调用实现超时(它们在单独的线程中运行).因此,我检测了他们的代码,并在循环和方法定义之后插入了以下代码:

I need to implement timeout for students' code calls (they run in separate threads). So I instrumented their code and inserted right after loop and method definitions the following code:

if (Thread.interrupted()) throw new InterruptedException();

问题是检查了InterruptedException,因此我必须在所有方法中添加throws声明,这可能会破坏覆盖方法的签名.

The problem is InterruptedException is checked, and therefore I have to add throws declarations to all methods, which can break overriding methods' signatures.

所以我以为我不能扔InterruptedException,但是不能扔掉,例如RuntimeException.我可以做吗?会有所区别吗?

So I thought I could not throw InterruptedException, but an unchecked one, e.g. RuntimeException. Can I do it? Will there be some difference?

在比赛代码中,我将学生代码作为futrure在ExecutorService中启动,并尝试使用get()超时来获得结果.

In my tournament code I start the students' code as a futrure in an ExecutorService and try to get the result using get() with timeout.

推荐答案

标准ExecutorService实现中的工作线程的中断状态将在任务完成时清除,并且出于测试是否执行任务的目的而将其忽略.任务在完成之前被取消(由Future.isCancelled()检测到).

The interrupt status of a worker thread in the standard ExecutorService implementations will be cleared when a task is completed, and it's ignored for the purposes of testing whether a task was canceled before completion (as detected by Future.isCancelled()).

因此,您可以放心地抛出未经检查的(运行时")异常,而不是InterruptedException,它不会干扰ExecutorService的操作.

So, you can safely throw an unchecked ("runtime") exception rather than InterruptedException, and it won't interfere with the operation of the ExecutorService.

但是,如果您仍然担心,可以通过重新设置中断状态来保留中断状态:

However, if you are still concerned, you can preserve the interrupt status by re-asserting it:

if (Thread.interrupted()) {
  Thread.currentThread().interrupt();
  throw new IllegalStateException("Time limit exceeded.");
}

或使用其他无法清除的方法:

Or using a different method that doesn't clear it:

if (Thread.currentThread().isInterrupted()) 
  throw new IllegalStateException("Time limit exceeded.");

通常,自定义运行时异常是一个坏主意,因为它们可能会导致泄漏抽象,但是在这里,代替IllegalStateException的自定义类型可能使您更容易区分超时异常与学生的运行时异常引发的异常.代码.

Normally custom runtime exceptions are a bad idea, because they can result in leaky abstractions, but here, a custom type in place of IllegalStateException may make it cleaner for you to distinguish your timeout exceptions from runtime exceptions raised by the student's code.

更新:仅当正确编写任务以支持中断并且您不相信学生这样做时,取消使用ExecutorService运行的任务才是可靠的.

Update: Canceling a task running with ExecutorService is only reliable if the task is written correctly to support interruption, and you can't trust students to do that.

因此,您的选择是:

  1. 手动查看源代码,必要时插入中断检测.
  2. 摆脱ExecutorService并自己创建工作线程.使用stop()stop(Throwable)方法在超时后终止线程.为了真正强大,请使用字节代码工程库(例如ASM)来自动分析已编译的插件代码,以查看它是否可以捕获您正在使用的Throwable(或ThreadDeath或自定义Throwable)工作线程.
  3. 分叉Java进程来运行代理代码,并在超时后终止整个进程.
  1. Manually review the source code, inserting interruption detection where necessary.
  2. Get rid of ExecutorService and create worker threads yourself. Use the stop() or stop(Throwable) method to terminate the threads after timeout. To be truly robust, use a byte code engineering library like ASM to automate analysis of the compiled plugin code to see if it can catch the Throwable (or ThreadDeath or the custom Throwable) you are using to stop() the worker thread.
  3. Fork Java processes to run the agent code, and kill the whole process after timeout.

这篇关于在停止线程时抛出InterruptedException是否必不可少?我可以使用其他异常类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆