当前位置: 首页 > 知识库问答 >
问题:

如果一个线程完成了它的最后一条语句的执行,那么它是否保证像显式调用return一样死亡?

白弘伟
2023-03-14

例如,以下面的代码段为例,

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创建的第一个线程似乎已经死亡,但真的是这样吗?

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

但是,在实际执行return之前可能会有一些延迟,因为这取决于调度器,所以如果调度器决定在执行exec.execute(()->{})之前不运行return语句,下一个提交给executor的runnable可能会被拒绝;在尝试区。

共有1个答案

上官淮晨
2023-03-14

是的,编译器的行为就像任何方法的结尾都包含return;语句一样。

不,你的代码不正确。

问题是两个线程可以以任何可能的方式交织。正如墨菲所说,能发生的事情(最终)会发生。

public static void main(String[] args) throws InterruptedException {
    final ExecutorService exec = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    Future<?> future = exec.submit(() -> {
        // Do work
    });

    try {
        future.get(); //blocking call
    } catch (ExecutionException e) {
        e.getCause().printStackTrace(); // The RuntimeException thrown in the lambda.
    }

    try {
        exec.submit(() -> {});
    } catch (RejectedExecutionException e) {
        // Shouldn't happen
    }
    exec.shutdown();
}

而队列长度为0的执行器实际上是可能的:

new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
 类似资料:
  • 问题内容: 只是一个简单的问题,如果我克隆一个进程,则克隆的进程的PID是相同的,是吗?fork()创建一个子进程,其PID不同,但其他所有事物都相同。Vfork()创建一个具有相同PID的子进程。Exec致力于将当前正在执行的流程更改为其他流程。 我在所有这些陈述中都正确吗? 问题答案: 不完全的。如果通过fork / exec或vfork / exec克隆进程,则将获得新的进程ID。将为您提供

  • 我是RxJava新手。我想从给定集合中下载每个TempoAccount实体的一些数据,并将其存储在map accountsWithProjects中。当上一个onNext(TempoAccount TempoAccount)的代码完成时,我想调用filterAccountsWithProjects(accountsWithProjects)方法。有什么简单的方法可以实现吗? 问题:在上面的代码中,

  • 问题内容: 有没有一种方法可以检查我是否在最后一条记录上?谢谢 问题答案: 使用此模式来标识和处理结果的最后一行:

  • 问题内容: 如果我使用如下代码: 它会死掉还是可以在之后提出其他查询?像将错误日志记录到另一个表的预定函数一样?如: “或”之后还有哪些其他选择?我没有在文档中找到它,任何线索都值得赞赏。 问题答案: 它必须死吗 恰恰相反, 它永远都不会。 PHP是一种不良遗传的语言。遗传很差。和错误消息是最差的雏形之一: 死掉会抛出错误消息,向潜在的攻击者透露一些系统内部信息 这会给无辜的用户带来奇怪的消息,并

  • 问题内容: 为了掌握Redis的一些基础知识,我遇到了一篇有趣的博客文章。 作者指出: Redis是具有epoll / kqueue的单线程,并且在I / O并发方面可以无限​​扩展。 我肯定会误解整个线程问题,因为我发现此语句令人困惑。如果程序是单线程的,它如何并发执行任何操作?如果服务器仍然是单线程的,为什么Redis操作是原子的那么好呢? 有人可以阐明这个问题吗? 问题答案: 好吧,这取决于