关闭两个 ExecutorService 实例
Shut down two instances of ExecutorService
我需要用一种方法正确关闭两个 Executor Service 实例。
这是我的简化代码:
ExecutorService executor1 = Executors.newSingleThreadExecutor();
ScheduledExecutorService executor2 = Executors.newSingleThreadScheduledExecutor();
// logic here
executor1.shutdown();
executor2.shutdown();
try {
if (!executor1.awaitTermination(1, TimeUnit.SECONDS)) {
executor1.shutdownNow();
}
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
try {
if (!executor2.awaitTermination(1, TimeUnit.SECONDS)) {
executor2.shutdownNow();
}
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
InterruptedException
转换为 IllegalStateException
因为我不希望这里有任何中断,这意味着我的应用程序进入非法状态。
我看到此解决方案中的一个缺陷 - 每当第一个执行程序在关闭时抛出异常,第二个执行程序将无法正确关闭。这里应该是正确的方法是什么?如何安全地关闭 ExecutorService
的两个实例?
我宁愿避免嵌套 try-finally
块,因为我可能需要添加第三个执行程序服务,代码将变得难以管理。
至于类似情况:
Apache Commons IO 有一个 closeQuietly()
可以关闭流(或者更确切地说是任何 Closeable
),同时忽略关闭期间的任何异常。
public void shutdownQuietly(ExecutorService executor)
{
try {
if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException ex) {
/* IGNORE */
}
}
如果你需要那些例外,你可以尝试一些更邪恶的技巧:
class MultiExecutorShutdown
{
private final List<InterrupedException> exceptions = new ArrayList<>();
public void shutdown(ExecutorService service)
{
try {
if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException ex) {
exceptions.add(ex);
}
}
public Optional<InterruptedException> getLastException()
{
if (exceptions.isEmpty()) {
return Optional.empty();
} else {
return exceptions.get(exceptions.size() - 1);
}
}
public Optional<InterruptedException> getFirstException()
{
if (exceptions.isEmpty()) {
return Optional.empty();
} else {
return exceptions.get(0);
}
}
}
[...]
MultiExecutorShutdown multiShutdown = new MultiExecutorShutdown();
multiShutdown.shutdown(executor1);
multiShutdown.shutdown(executor2);
multiShutdown.shutdown(executor3);
Optional<InterruptedException> exception = multiShutdown.getLastException();
// alternative:
// Optional<InterruptedException> exception = multiShutdown.getFirstException();
if (exception.isPresent()) {
throw new IllegalStateException(exception.get());
}
如果您还需要失败的执行器,您还可以修改 MultiExecutorShutdown
以保留(有序的)映射 ExecutorService -> Exception
。
您还可以将 throw 推入 MultiExecutorShutdown
本身,使其更有用。最后,整个事情可以——当然——被抽象出来,这样它就可以接受一个函数,调用它并记录任何抛出的异常。
我需要用一种方法正确关闭两个 Executor Service 实例。
这是我的简化代码:
ExecutorService executor1 = Executors.newSingleThreadExecutor();
ScheduledExecutorService executor2 = Executors.newSingleThreadScheduledExecutor();
// logic here
executor1.shutdown();
executor2.shutdown();
try {
if (!executor1.awaitTermination(1, TimeUnit.SECONDS)) {
executor1.shutdownNow();
}
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
try {
if (!executor2.awaitTermination(1, TimeUnit.SECONDS)) {
executor2.shutdownNow();
}
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
InterruptedException
转换为 IllegalStateException
因为我不希望这里有任何中断,这意味着我的应用程序进入非法状态。
我看到此解决方案中的一个缺陷 - 每当第一个执行程序在关闭时抛出异常,第二个执行程序将无法正确关闭。这里应该是正确的方法是什么?如何安全地关闭 ExecutorService
的两个实例?
我宁愿避免嵌套 try-finally
块,因为我可能需要添加第三个执行程序服务,代码将变得难以管理。
至于类似情况:
Apache Commons IO 有一个 closeQuietly()
可以关闭流(或者更确切地说是任何 Closeable
),同时忽略关闭期间的任何异常。
public void shutdownQuietly(ExecutorService executor)
{
try {
if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException ex) {
/* IGNORE */
}
}
如果你需要那些例外,你可以尝试一些更邪恶的技巧:
class MultiExecutorShutdown
{
private final List<InterrupedException> exceptions = new ArrayList<>();
public void shutdown(ExecutorService service)
{
try {
if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException ex) {
exceptions.add(ex);
}
}
public Optional<InterruptedException> getLastException()
{
if (exceptions.isEmpty()) {
return Optional.empty();
} else {
return exceptions.get(exceptions.size() - 1);
}
}
public Optional<InterruptedException> getFirstException()
{
if (exceptions.isEmpty()) {
return Optional.empty();
} else {
return exceptions.get(0);
}
}
}
[...]
MultiExecutorShutdown multiShutdown = new MultiExecutorShutdown();
multiShutdown.shutdown(executor1);
multiShutdown.shutdown(executor2);
multiShutdown.shutdown(executor3);
Optional<InterruptedException> exception = multiShutdown.getLastException();
// alternative:
// Optional<InterruptedException> exception = multiShutdown.getFirstException();
if (exception.isPresent()) {
throw new IllegalStateException(exception.get());
}
如果您还需要失败的执行器,您还可以修改 MultiExecutorShutdown
以保留(有序的)映射 ExecutorService -> Exception
。
您还可以将 throw 推入 MultiExecutorShutdown
本身,使其更有用。最后,整个事情可以——当然——被抽象出来,这样它就可以接受一个函数,调用它并记录任何抛出的异常。