gpt4 book ai didi

java - 如果一个线程执行完最后一条语句,一旦完成,它是否会像显式调用 return 一样保证死亡?

转载 作者:行者123 更新时间:2023-12-01 19:58:23 25 4
gpt4 key购买 nike

例如,采用此代码片段,

static volatile boolean isDone = false;
public static void main(String[] args) throws InterruptedException {
// I know ArrayBlockingQueue cannot take 0 as the constructor arg, but please for the sake of example, let's pretend this was legal
final ExecutorService exec = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(0));
exec.execute(() -> {
isDone = true;
// does the compiler add a return statement here?
});
while (!isDone){
}
try {
exec.execute(() -> {});
} catch (RejectedExecutionException e) {
System.out.println("What if this might actually happen in a super bad timing by the scheduler??");
}
exec.shutdown();
}

看起来 ExecutorService 创建的第一个线程已经死了,但事实真的是这样吗?

在线程 API 中 https://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html它说如果 run() 方法返回,那么线程就死了,但我没有显式调用返回,并且我不确定运行时或编译器实际上做了什么。

例如,它可能会在 isDone = true 之后和封闭的 } 之前隐式添加 return 语句,例如

exec.execute(() -> {
isDone = true;
return;
});

但是,在实际返回之前可能会有一些延迟,因为这取决于调度程序,因此如果调度程序决定在执行 exec 之前不运行该 return 语句,则下一个提交给执行程序的可运行程序可能会被拒绝。执行(() -> {});在 try block 中。

最佳答案

exec.execute(() -> isDone = true); 之间没有技术差异和exec.execute(() -> { isDone = true; return; });

但是,这并没有说明 ExecutorService 。除此之外,在观察到完成对 isDone 的写入后,可能会经过任意时间量。以及 return; 的执行声明,即使代码完成也不能保证 ExecutorService已准备好接受新工作。

当您调用execute时或submit并且工作线程数已经达到指定的核心线程数,只有 offer 才会成功。调用队列成功。以SynchronousQueue为例,只有当工作线程调用 take() 时,它才会成功。已经在队列中了。从代码返回与已经调用 take() 不同。在队列中。

当您使用 future 来确保完成工作时,这甚至不会改变,例如

final ExecutorService exec = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>() {
@Override
public Runnable take() throws InterruptedException {
System.out.println(".take()");
return super.take();
}
});
Future<?> f = exec.submit(() -> { return; });
f.get();
try {
exec.execute(() -> {});
} catch (RejectedExecutionException e) {
System.err.println(
"What if this might actually happen in a super bad timing by the scheduler??");
}
exec.shutdown();

在我的机器上偶尔会失败。 print 语句足以减慢操作速度,让启动线程有时会重载。

Future没有帮助,就像 get() 一样返回后,您可以确定您的代码已完成,作为其调用者,FutureTask确实已经完成了 future,但是,这与已经调用工作线程不同 take()在队列中或更准确地说,已到达 take() 内的点足以让 offer() 的方法调用成功。

同样的问题也适用于已满的有界队列,其中下一个 offer()仅当工作线程的 take() 时,调用才能成功调用删除 offer() 之前的元素打电话。

当您使用ThreadPoolExecutor时具体来说,您可以获取队列并使用 offer手动,以通知执行器何时尚未准备好。

但是,一般的解决方案不是使用线程计数或队列容量,因为它们会使您的应用程序依赖于微妙的线程调度或执行计时细节。或者使用不同的RejectedExecutionHandlerThreadPoolExecutor.AbortPolicy .

关于java - 如果一个线程执行完最后一条语句,一旦完成,它是否会像显式调用 return 一样保证死亡?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48700183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com