所以我一直在检查使用Closeable
与ExecutorService
接口的可能性。然后我看到Lukas回答here这只是使用方法参考:
ExecutorService service = Executors.newSingleThreadExecutor();
try (Closeable close = service::shutdown) {
}
所以我一直在挖掘并希望在try块中初始化服务:
@Test(expected = RejectedExecutionException.class)
public void singleThreadTest() throws Exception {
ExecutorService es = null;
try (Closeable closeable = (es = Executors.newSingleThreadExecutor())::shutdown){
es.execute(()->System.out.println("executed " + Thread.currentThread().getId()));
}
System.out.println("executed " + Thread.currentThread().getId());
System.out.println(es.isShutdown());
es.execute(()->{});
}
这部分相当不错,有点困惑,但如果有异常,我会相信,然后我试过了:
@Test(expected = RejectedExecutionException.class)
public void singleThreadTest() throws Exception {
ExecutorService es = null;
try (Closeable closeable = es::shutdown){
es = Executors.newSingleThreadExecutor();
es.execute(()->System.out.println("executed " + Thread.currentThread().getId()));
}
System.out.println("executed " + Thread.currentThread().getId());
System.out.println(es.isShutdown());
es.execute(()->{});
}
对于这个代码块,我得到NullPointerException
但代码块已成功执行(新线程已创建,但在close()阶段我遇到异常)。我注意到,当我宣布:
Closeable closeable = es::shutdown
es必须(有效)最终,这个问题只发生在双冒号运算符中。即低于一个不编译:
try (Closeable closeable = new Closeable() {
@Override
public void close() throws IOException {
es.shutdown();
}
}){
这是一个错误吗?这是什么原因? *方法参考impl? * IDE * JVM(oracle - debian)?
跟进:
@Test(expected = RejectedExecutionException.class)
public void singleThreadTest() throws Exception {
ExecutorService es = null;
es = Executors.newSingleThreadExecutor();
es = Executors.newSingleThreadExecutor();
es = null;
try (Closeable closeable = ()->es.shutdown();){
es = Executors.newSingleThreadExecutor();
es.execute(()->System.out.println("executed " + Thread.currentThread().getId()));
}
System.out.println("executed " + Thread.currentThread().getId());
System.out.println(es.isShutdown());
es.execute(()->{});
}
此代码无法编译,但确实如此:
@Test(expected = RejectedExecutionException.class)
public void singleThreadTest() throws Exception {
ExecutorService es = null;
es = Executors.newSingleThreadExecutor();
es = Executors.newSingleThreadExecutor();
es = null;
try (Closeable closeable = es::shutdown;){
es = Executors.newSingleThreadExecutor();
es.execute(()->System.out.println("executed " + Thread.currentThread().getId()));
}
System.out.println("executed " + Thread.currentThread().getId());
System.out.println(es.isShutdown());
es.execute(()->{});
}
答案 0 :(得分:1)
不,这不是一个错误。您要关闭的变量/参数的值需要在捕获点知道。
当你得到一个NPE时,因为你在es = null
时声明了匿名内部类(或lambda或方法引用)。这就是被捕获的价值:未来的任务没有被看到。
Why can method reference use non-final variables?
为了阻止你犯这个错误,有一个限制“X必须(有效)最终”,这意味着如果你试图改变你想要捕获的变量X的值,它将无法编译。
Why are only final variables accessible in anonymous class?
基本上,您需要将代码重新排列为以下内容:
final ExecutorService es = Executors.newSingleThreadExecutor();
try (Closeable closeable = es::shutdown) {
// ...