计算程序所需线程总数:
线程数 = CPU可用核心数/(1-阻塞系数)
1、处理器可用核心数
poolSize:4
time:15003
current call 10
current call 9
current call 8
current call 7
current call 6
current call 5
current call 4
current call 3
current call 2
current call 1
poolSize:40
time:10001
current call 10
current call 9
current call 8
current call 7
current call 6
current call 5
current call 4
current call 3
current call 2
current call 1
线程数 = CPU可用核心数/(1-阻塞系数)
其中阻塞系数的取值在0-1之间。
计算密集型任务的阻塞系数为0,而IO密集型任务的阻塞系数则接近于1。一个完全阻塞的任务是注定要挂掉的,所以我们无须担心阻塞系数会达到1。
为了更好的确定程序所需线程数,我们需要知道下面两个关键参数:1、处理器可用核心数
2、任务的阻塞系数
第一个参数很容易确定(Runtime.getRuntime().availableProcessors())。
阻塞系数可以采用一些性能分析工具或java.lang.managenment API来确定线程话在系统I/O操作上的时间与CPU密集任务所消耗的时间比值。
Demo:
// 测试公式:线程数=CPU可用核心数/(1-阻塞系数)
@Test
public void testInvokeAll() throws InterruptedException, ExecutionException {
// 向 Java 虚拟机返回可用处理器的数目(我当前机器是i3双核四线程,返回为4)
int numberOfCores = Runtime.getRuntime().availableProcessors();
double blockingCoefficient = 0;
int poolSize = (int) (numberOfCores / (1 - blockingCoefficient));
System.out.println("poolSize:" + poolSize);
// 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
ExecutorService services = Executors.newFixedThreadPool(poolSize);
List<Callable<String>> tasks = new LinkedList<Callable<String>>();
for (int i = 10; i >= 1; i--) {
final String reStr = "current call " + i;
final int j = i;
tasks.add(new Callable<String>() {
@Override
public String call() throws Exception {
// 模拟阻塞
TimeUnit.SECONDS.sleep(j);
return reStr;
}
});
}
long beginTime = System.currentTimeMillis();
List<Future<String>> invokeValues = services.invokeAll(tasks);
System.out.println("time:" + (System.currentTimeMillis() - beginTime));
Iterator<Future<String>> iter = invokeValues.iterator();
while (iter.hasNext()) {
System.out.println(iter.next().get());
}
services.shutdown();
}
当我们阻塞系数设置为0,消耗时间为15003;阻塞系数设置为0.9时,消耗时间为10001。
poolSize:4
time:15003
current call 10
current call 9
current call 8
current call 7
current call 6
current call 5
current call 4
current call 3
current call 2
current call 1
poolSize:40
time:10001
current call 10
current call 9
current call 8
current call 7
current call 6
current call 5
current call 4
current call 3
current call 2
current call 1