最近我接受采访,面试官问我什么是你可以分配给线程池的最大线程。我回答他这将取决于硬件组合。 我也可以通过增加线程池中的线程来手动测试执行。
他似乎对此并不满意。
任何人都可以告诉我们如何决定我们应该使用的最大线程数以获得更好的性能。任何指南链接将不胜感激(在核心Java应用程序中)
答案 0 :(得分:5)
任何人都可以告诉我们如何确定我们应该使用的最大线程数以获得更好的性能 - 它绝对不是最大线程数量。
为获得最佳性能,线程数应等于处理器核心数(不要忘记使用 -XmsYYYYM 和 -XmxYYYYM ,如果没有它们,当处理器没有为线程分配线程时,你可能会遇到这种情况。)
关于最大线程您的答案是否正确,这取决于硬件和操作系统。 在linux上可以检查:
cat /proc/sys/kernel/threads-max
<强>编辑。强>
您可以使用 Integer.MAX_VALUE
创建线程池但您限制最大线程使用量。 在我的笔记本上。命令“cat / proc / sys / kernel / threads-max”向我显示 126987 。
我跑的代码:
package com.stackoverflow.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestMaxAmountOfThreads {
public static void main(String[] args) {
ExecutorService serivce = Executors.newFixedThreadPool(Integer.MAX_VALUE);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
serivce.submit(new Runnable() {
public void run() {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
}
}
});
System.out.println(i);
}
}
}
输出:
31850
线程“main”中的异常java.lang.OutOfMemoryError:无法 在java.lang.Thread.start0创建新的本机线程(本机方法) 在java.lang.Thread.start(Thread.java:714)at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:949) 在 java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360) 在 java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110) 在 com.stackoverflow.test.TestMaxAmountOfThreads.main(TestMaxAmountOfThreads.java:10)
所以我只能使用 31850 线程,而不使用jvm调优。
答案 1 :(得分:0)
ThreadPoolExecutor
类构造函数定义如下 - :
public ThreadPoolExecutor(int corePoolSize,**int maximumPoolSize**,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
您可以将整数(Integer.MAX_VALUE
)的最大值分配给maximumPoolSize。将线程池大小设置得太大可能会导致性能问题。如果同时执行的线程太多,则任务切换开销成为一个重要因素。
答案 2 :(得分:0)
计算可用于在Threadpool中获得更好性能的最大线程数
这个问题的答案完全取决于每个线程将执行的任务类型。
一方面,如果您的程序是CPU bound,则运行线程的数量不应高于CPU核心数。某些英特尔处理器具有is known to affect CPU bound tasks的“超线程”功能,因此您应该考虑禁用超线程。
另一方面,如果您的程序不受CPU限制但完全IO bound,那么线程数不应高于可用内核数的2或3倍。如果你有8个内核,那么对于IO绑定程序,你不应该超过24个线程。
在中间,如果您的线程池需要执行混合CPU绑定和IO绑定操作,您应该使用不同的输出测试和测量性能,并根据您的具体情况确定合理的数字。没有理论上的方法可以找到具体的数字,你应该为你的具体应用程序运行一些具体的基准测试。
这当然完全取决于你的程序,如果你有一个完全IO绑定的程序,那么我会说你只坚持一个线程并利用主要平台中可用的非阻塞异步IO API。在Java中,我们有Non-blocking IO (NIO)。