java - 并发运行 100,000 个进程

标签 java concurrency jvm

我正在模拟一个银行系统,其中要运行 100,000 笔交易。每种类型的事务都实现了可运行的,并且我有各种类型的事务可以发生。

transactions 是一个 Runnable 数组。

理想情况下,以下代码可以解决我的问题:

for (Transaction transaction : transactions) {
    new Thread(transaction).start();
}

但是,显然 java.lang.OutOfMemoryError: unable to create new native thread 在尝试启动 100,000 个线程时必然会发生。

接下来我尝试实现一个 ExecutorService 来创建一个线程池来管理我的 100,000 个可运行对象。

ExecutorService service;
int cpus = Runtime.getRuntime().availableProcessors();
// cpus == 8 in my case
service = Executors.newFixedThreadPool(cpus);

for (Transaction transaction : transactions) {
    service.execute(transaction);
}

尝试这种方法时,长进程会“占用”JVM。例如,一种类型的交易需要 30 - 60 秒才能执行。在分析应用程序时,不允许其他线程在长事务发生时运行。

In this case, thread 6 did not allow any other threads to run until its single transaction was complete

在这种情况下,线程 6 在其处理完成之前不允许任何其他线程运行。

所以我的问题是:如何在不遇到内存问题的情况下尽可能快地运行 100,000 个事务?如果 ExecutorService 是答案,那么我如何才能阻止非常长的事务占用 JVM 并允许其他事务并发运行?

编辑:

我故意强制某些类型的事务发生 30 - 60 秒,以确保我的线程程序正常工作。每笔交易锁定一个账户,共有 10 个账户。这是我占用 JVM 的方法:(由 run() 调用)

public void makeTransaction() {
    synchronized(account) {
        long timeStarted = System.nanoTime();
        long timeToEnd = timeStarted + nanos;

        this.view = new BatchView(transactionNumber, account.getId());

        this.displayView();

        while(true) {
            if(System.nanoTime() % 1000000000 == 0) {
                System.out.println("batch | " + account.getId());
            }

            if(System.nanoTime() >= timeToEnd) {
                break;
            }
        }
    }
}

每次运行此事务时,只有一个帐户被锁定,剩下 9 个帐户应可用于处理。 为什么 JVM 不再处理任何线程,而是挂起直到这个长事务完成?

这里是项目的缩小版本的链接,用于演示问题:project

最佳答案

When profiling the application, no other threads are being allowed to run while the long transaction takes place.

很可能,此任务正在使用单线程资源。即 ti 的编写方式会阻止并发使用。

How can I run 100,000 transactions as fast as possible without running into memory problems?

如果事务受 CPU 限制,您应该有一个与您拥有的 CPU 数量大小相同的池。

如果事务依赖于数据库,您应该考虑对它们进行批处理以更有效地利用数据库。

If ExecutorService is the answer, then how can I stop very long transactions from hogging the JVM and allow other transactions to run concurrently?

使交易更短。如果您有一个运行时间超过几毫秒的任务,您应该弄清楚为什么要花这么长时间。我将首先查看网络/IO 必须如何使用和分析任务。大多数交易(如果您有大量交易)应该在 0.01 秒左右或更理想。

您应该仔细考虑如何使用共享资源。如果您的任务过多地使用相同的资源,您可能会发现多线程并不快,甚至更慢。

关于java - 并发运行 100,000 个进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29160702/

相关文章:

mysql - "FOR UPDATE"v/s "LOCK IN SHARE MODE": Allow concurrent threads to read updated "state" value of locked row

java - JVM 崩溃..如何获取错误日志或核心转储

java - Java中什么时候为对象(PO​​JO)分配内存

java - Maven 构建中的契约(Contract)检查

java - 尝试在 Android Activity 中执行简单命令时出错

multithreading - 这是Go中的惯用工作线程池吗?

jvm - 更好地了解JVM

java - JTextArea 行到 ArrayList<String>

java - Hibernate一对一映射问题

java - JMS消息监听器Weblogic的并发处理