java - 在没有线程暂停的情况下执行 ExecutorService 中的任务

标签 java multithreading executorservice java-17

我有一个有8个线程的线程池

private static final ExecutorService SERVICE = Executors.newFixedThreadPool(8);

我的机制模拟 100 个用户(100 个任务)的工作:

List<Callable<Boolean>> callableTasks = new ArrayList<>();
for (int i = 0; i < 100; i++) { // Number of users == 100
    callableTasks.add(new Task(client));
}
SERVICE.invokeAll(callableTasks);
SERVICE.shutdown();

用户执行生成文档的任务。

  1. 获取任务的UUID;
  2. 每 10 秒获取一次任务状态;
  3. 如果任务准备就绪,获取文档。
public class Task implements Callable<Boolean> {

    private final ReportClient client;

    public Task(ReportClient client) {
        this.client = client;
    }

    @Override
    public Boolean call() {
        final var uuid = client.createDocument(documentId);
        GetStatusResponse status = null;
        do {
            try {
                Thread.sleep(10000); // This stop current thread, but not a Task!!!!
            } catch (InterruptedException e) {
                return Boolean.FALSE;
            }
            status = client.getStatus(uuid);
        } while (Status.PENDING.equals(status.status()));
        final var document = client.getReport(uuid);
        return Boolean.TRUE;
    }
}

我想把空闲时间(10 秒)给另一个任务。但是当命令Thread.sleep(10000);被调用时,当前线程暂停执行。前 8 个任务暂停,92 个任务等待 10 秒。如何同时执行 100 个正在进行的任务?

最佳答案

Answer by Yevgeniy对于今天的 Java,看起来是正确的。您既想吃蛋糕也想吃蛋糕,因为您希望线程在重复任务之前 hibernate ,但您还希望该线程执行其他工作。这在今天是不可能的,但在未来可能会。

Loom 项目

在当前的 Java 中,Java 线程直接映射到主机 OS线。在所有常见的操作系统中,例如 macOS、BSD、Linux、Windows 等,当在主机线程中执行的代码阻塞(停止等待 sleep 、或存储 I/O、或网络 I/O 等)时,线程也会阻塞 block 。被阻塞的线程挂起,主机操作系统通常在那个未使用的内核上运行另一个线程。但关键是挂起的线程不会执行进一步的工作,直到您对 sleep 的阻塞调用返回。

这张图在不久的将来可能会改变。 Project Loom寻求添加 virtual threads到 Java 中的并发设施。

在这项新技术中,许多 Java 虚拟线程被映射到每个主机操作系统线程。处理许多 Java 虚拟线程是由 JVM 而不是操作系统来管理的。当 JVM 检测到虚拟线程的执行代码被阻塞时,该虚拟线程被“停放”,由 JVM 搁置,另一个虚拟线程换出以在该“真实”主机操作系统线程上执行。当另一个线程从它的阻塞调用返回时,它可以被重新分配给一个“真正的”主机操作系统线程以进一步执行。在 Project Loom 下,主机操作系统线程保持忙碌,在任何挂起的虚拟线程有工作要做时从不空闲。

虚拟线程之间的这种交换非常高效,因此可以在传统计算机硬件上同时运行数千甚至数百万个线程。

使用虚拟线程,您的代码确实会像您希望的那样工作:Java 中的阻塞调用不会阻塞主机操作系统线程。但是虚拟线程是实验性的,仍在开发中,安排为 preview featureJava 19 .包含 Loom 技术的 Java 19 早期访问版本是 available now供您尝试。但对于今天的生产部署,您需要遵循 Yevgeniy 的回答中的建议。


请对我的报道持保留态度,因为我不是并发方面的专家。您可以从真正的专家、Project Loom 团队成员(包括 Ron Pressler 和 Alan Bateman)的文章、访谈和演示中听到它。

关于java - 在没有线程暂停的情况下执行 ExecutorService 中的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72426404/

相关文章:

java - 程序卡在主java线程中

java - newCachedThreadPool如何复用线程?

c++ - 多线程 MongoDB C++ 客户端应用程序 : multiple DBClientConnections vs. 单个互斥锁?

java - Appium android - 按属性查找元素

Javafx Alert 导致程序卡住

java - 在迭代时使用 'if' 条件查找项目与使用 get(key),当你已经需要迭代时

c# - 暂停程序以允许用户在 wpf 中进行交互

java - 关于ExecutorService的shutdownNow

javarabbitmq带有Executor线程,创建的线程保持运行。如何确保线程被杀死?

java - AudioInputStream() 不会停止