Java 停止线程时抛出InterruptedException是否必要?我可以使用其他异常类型吗?
我有学生代码的比赛代码。因此,我无法控制学生的代码 我需要为学生的代码调用实现超时(它们在单独的线程中运行)。因此,我检测了他们的代码,并在循环和方法定义之后插入了以下代码:Java 停止线程时抛出InterruptedException是否必要?我可以使用其他异常类型吗?,java,multithreading,Java,Multithreading,我有学生代码的比赛代码。因此,我无法控制学生的代码 我需要为学生的代码调用实现超时(它们在单独的线程中运行)。因此,我检测了他们的代码,并在循环和方法定义之后插入了以下代码: if (Thread.interrupted()) throw new InterruptedException(); 问题是InterruptedException已检查,因此我必须向所有方法添加throws声明,这可能会破坏重写方法的签名 所以我认为我不能抛出中断异常,而是一个未经检查的异常,例如运行时异常。我能做吗
if (Thread.interrupted()) throw new InterruptedException();
问题是InterruptedException
已检查,因此我必须向所有方法添加throws
声明,这可能会破坏重写方法的签名
所以我认为我不能抛出中断异常
,而是一个未经检查的异常,例如运行时异常
。我能做吗?会有什么不同吗
在我的竞赛代码中,我在
执行器服务中启动学生代码,并尝试使用带有超时的get()
获得结果。InterruptedException由java规范建议:您可以在此处找到更多信息
InterruptedException是java规范建议的:您可以在这里找到更多信息
如果您想要一个简单的超时,并且不关心代码是否优雅地终止,您可以使用。不鼓励使用stop(),因为不管它当前在做什么,它都会在该线程中抛出ThreadDeatheException。通过注入在每个循环中抛出异常的代码,您所做的基本相同(除了jdk代码正常终止)。因此,在这种特殊情况下,我建议使用stop()
但是,如果您更希望取消选中InterruptedException,那么有一个错误
下面是一个如何使用ScheduledExecutorService停止线程的示例
void runWithHardTimeOut(final Runnable task, long timeout, TimeUnit unit) {
final Thread[] runner = new Thread[1];
final AtomicBoolean done = new AtomicBoolean(false);
Runnable killer = new Runnable() {
@Override
public void run() {
if (!done.get()) {
while (runner[0] == null);
if (done.get()) {
return;
} else {
runner[0].stop();
}
}
}
};
final Runnable r = new Runnable() {
@Override
public void run() {
try {
runner[0] = Thread.currentThread();
killerExecutor.schedule(killer, timeout, unit);
task.run();
done.set(true);
} catch (ThreadDeath wrench) {}
}
};
executor.execute(r);
}
如果您想要一个简单的超时,并且不关心代码是否优雅地终止,那么可以使用。不鼓励使用stop(),因为不管它当前在做什么,它都会在该线程中抛出ThreadDeatheException。通过注入在每个循环中抛出异常的代码,您所做的基本相同(除了jdk代码正常终止)。因此,在这种特殊情况下,我建议使用stop()
但是,如果您更希望取消选中InterruptedException,那么有一个错误
下面是一个如何使用ScheduledExecutorService停止线程的示例
void runWithHardTimeOut(final Runnable task, long timeout, TimeUnit unit) {
final Thread[] runner = new Thread[1];
final AtomicBoolean done = new AtomicBoolean(false);
Runnable killer = new Runnable() {
@Override
public void run() {
if (!done.get()) {
while (runner[0] == null);
if (done.get()) {
return;
} else {
runner[0].stop();
}
}
}
};
final Runnable r = new Runnable() {
@Override
public void run() {
try {
runner[0] = Thread.currentThread();
killerExecutor.schedule(killer, timeout, unit);
task.run();
done.set(true);
} catch (ThreadDeath wrench) {}
}
};
executor.execute(r);
}
标准ExecutorService
实现中工作线程的中断状态将在任务完成时被清除,并且为了测试任务是否在完成前被取消(由Future.isCancelled()
检测到),将忽略该中断状态
因此,您可以安全地抛出未经检查的(“运行时”)异常,而不是InterruptedException
,并且它不会干扰ExecutorService
的操作
但是,如果您仍然担心,可以通过重新断言中断状态来保持中断状态:
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Time limit exceeded.");
}
或者使用其他无法清除的方法:
if (Thread.currentThread().isInterrupted())
throw new IllegalStateException("Time limit exceeded.");
通常情况下,自定义运行时异常是个坏主意,因为它们可能会导致抽象泄漏,但在这里,用自定义类型代替IllegalStateException
,可以更清晰地区分超时异常和学生代码引发的运行时异常
更新:只有在正确编写任务以支持中断的情况下,取消使用ExecutorService
运行的任务才是可靠的,您不能相信学生会这样做
因此,您的选择是:
手动查看源代码,必要时插入中断检测
摆脱ExecutorService
,自己创建工作线程。使用stop()
或stop(Throwable)
方法在超时后终止线程。为了实现真正的健壮性,可以使用诸如ASM之类的字节码工程库来自动分析编译后的插件代码,以查看它是否能够捕获用于停止工作线程的Throwable
(或ThreadDeath
或自定义Throwable
)李>
标准
ExecutorService
实现中工作线程的中断状态将在任务完成时被清除,并且为了测试任务是否在完成前被取消(由Future.isCancelled()
检测到),将忽略该中断状态
因此,您可以安全地抛出未经检查的(“运行时”)异常,而不是InterruptedException
,并且它不会干扰ExecutorService
的操作
但是,如果您仍然担心,可以通过重新断言中断状态来保持中断状态:
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Time limit exceeded.");
}
或者使用其他无法清除的方法:
if (Thread.currentThread().isInterrupted())
throw new IllegalStateException("Time limit exceeded.");
通常情况下,自定义运行时异常是个坏主意,因为它们可能会导致抽象泄漏,但在这里,用自定义类型代替IllegalStateException
,可以更清晰地区分超时异常和学生代码引发的运行时异常
更新:只有在正确编写任务以支持中断的情况下,取消使用
ExecutorService
运行的任务才是可靠的,您不能相信学生会这样做
因此,您的选择是:
stop()
或stop(Throwable)
方法在超时后终止线程。为了实现真正的健壮性,可以使用诸如ASM之类的字节码工程库来自动分析编译后的插件代码,以查看它是否能够捕获用于停止工作线程的Throwable
(或ThreadDeath
或自定义Throwable
)李>