【问题标题】:How to execute tens of thousands of async operations per second that each have a three second wait time?如何每秒执行数以万计的异步操作,每个操作都有三秒的等待时间?
【发布时间】:2016-10-08 13:48:16
【问题描述】:

我需要在一个应用程序中每秒执行数万个 IO 绑定操作,每个操作都有 3 秒的延迟。在 node.js 中,这可以通过以下方式轻松完成:

var events = require('events');
var eventEmitter = new events.EventEmitter();

var count = 0;

var connectHandler = function connected() {
    setTimeout(function() {
        count++;
        console.log('task complete ' + count);
    }, 3000);
}

for (var i = 0; i < 30000; i++) {
    eventEmitter.on('mockedIOTask', connectHandler);
}

eventEmitter.emit('mockedIOTask');

如何在 Java 应用程序中实现这一点?我尝试了以下方法,但它一次只执行 3 个任务(原因很明显):

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;

public class Main {
    public static void main(String[] args) {
        //ExecutorService threadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 30000; i++) {
            final int count = i;
            ForkJoinPool.commonPool().submit(() -> {
                try {
                    Thread.sleep(3000);
                    System.out.println("task complete" + count);
                } catch (InterruptedException e) {
                }
            });
        }
        // Keep the program alive
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
        }
    }
} 

【问题讨论】:

  • 看起来像 3 秒超时而不是 3 秒延迟。每个任务仅在 Node.js 中的单个线程中执行。目前尚不清楚这两个程序试图做什么。
  • 应用程序正在模拟一个 IO 绑定任务,然后在 IO 绑定任务完成后执行一些操作(在这种情况下,打印到控制台)。我想知道如何在 java 应用程序中模仿 node.js 应用程序的行为。

标签: java node.js concurrency


【解决方案1】:

您可以使用 ScheduledExecutorService 在 3 秒后执行 30K 任务

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
List<Future<?>> tasks = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
    final int count = i;
    tasks.add(ses.submit(() -> System.out.println("task complete" + count)));
}
for (Future f : tasks) f.get();
ses.shutdown();

如果你想添加 IO 绑定操作,我会先从阻塞操作开始,然后再迁移到使用 netty 之类的库来处理非阻塞 IO。

【讨论】:

  • 感谢您的意见。每个 runnable 将执行一些 IO 绑定任务,然后在 IO 任务之后执行操作。通过将 Thread.sleep(3000); 添加到可运行对象来模拟代码中的任务,可以将代码减少到每 3 秒执行一个任务。
  • @newToScala 正确,这是您需要使用更多线程和/或非阻塞操作的地方。执行此操作的最佳方式取决于您的用例。
  • 首先需要为您所做的一切提供异步 API。对于低级网络 IO,有 Netty,但对于数据库查询,什么都没有。顺便说一句,线程是一种非常便宜的资源。您不应该害怕将您的操作系统限制提高到 100,000 甚至 1,000,000。
  • @MarkoTopolnik java 9 将具有异步数据库。虽然在这种情况下,数据库可能一次不能处理超过 10 个。
  • 你的意思是“10k 一次”?是的,它可以接受 10,000 个连接,但它实际上不可能运行 10,000 个查询。他们只会排队,这本来可以在客户端完成并避免大量资源浪费。
猜你喜欢
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多