CPU循环和内存中线程的粗略“成本”是多少?

时间:2009-09-29 13:52:37

标签: java multithreading

在java中使用线程的粗略“成本”是多少?是拇指/经验值的任何规则,一个线程的创建需要多少内存?是否粗略估计创建线程需要多少CPU周期?

上下文:在Web应用程序的servlet中,我希望并行化内容创建,因为内容的一部分是基于文件的,基于数据库的以及基于Web服务的。但这意味着对于每个“http-request-thread”(我的serlvet容器),我将有两到四个额外的线程。请注意,我将在Java 6中使用ExecutorService

当我在Web服务器上使用数百到数千个Java线程时,我应该期待什么?

3 个答案:

答案 0 :(得分:15)

每个线程都有自己的堆栈,因此会立即产生内存影响。对于Java 6,512k,默认线程堆栈大小为IIRC(不同的JVM /版本可能具有不同的默认值)。可以使用-Xss选项调整此数字。因此,使用数百个线程将对VM消耗的内存产生影响(很可能在任何CPU影响之前,除非这些线程正在运行)。

我见过客户遇到与线程/内存相关的问题,因为它不是一个明显的链接。创建100,000个线程(使用执行程序/池等)是微不足道的,并且内存问题似乎不会立即归因于此。

如果您为许多客户端提供服务,您可能需要查看Java NIO API,特别是multiplexing,它允许异步网络编程。这将允许您只使用一个线程处理许多客户端,从而减少对大量线程的需求。

答案 1 :(得分:1)

这取决于:它取决于操作系统,Java版本和CPU。解决这个问题的唯一方法是尝试并测量结果。

由于您将使用ExecutorService,因此控制线程数将很简单。不要使用太少或请求将叠加。如果使用太多,在Java用完线程之前很久就会遇到文件系统和数据库的性能问题。

答案 2 :(得分:0)

在准备有关纤维(又称项目织机)的杂志文章期间,我运行了一些简单的测试(Windows 10,JDK-Loom 15.b3):

AtomicInteger counter = new AtomicInteger(T);
AtomicBoolean go = new AtomicBoolean(false);
for (int i = 0; i < 10000; i++) {
  Thread.newThread(Thread.VIRTUAL, () -> { // <-- remove Thread.VIRTUAL for plain Threads
    while (!go.get()) Thread.sleep(1);
    counter.decrementAndGet();
  }).start();
}

我的Windows桌面(i7-8700K)需要大约400000毫秒来创建所有10000个线程,另外需要200毫秒来运行计数器。

令人惊讶的是,我无法确定每个线程512k的内存消耗(根据其他一些消息来源为1Mb)。 Windows内存监视器显示,所有10000个线程(每个线程50k)的额外内存消耗仅为500Mb


Project Loom Fibers设法分别在30 ms和50 ms中运行测试,并且没有可测量的内存消耗。