【发布时间】:2016-02-23 15:40:50
【问题描述】:
默认情况下,Java 流由common thread pool 处理,该common thread pool 使用默认参数构造。正如another question 中已回答的那样,可以通过指定自定义池或设置java.util.concurrent.ForkJoinPool.common.parallelism 系统参数来调整这些默认值。
但是,我无法通过这两种方法中的任何一种来增加分配给流处理的线程数。例如,考虑下面的程序,它处理包含在其第一个参数中指定的文件中的 IP 地址列表并输出解析的地址。在具有大约 13000 个唯一 IP 地址的文件上运行此程序,我发现使用 Oracle Java Mission Control 的线程少至 16 个。其中,只有五个是ForkJoinPool 工人。然而,这个特定的任务会从更多的线程中受益,因为线程大部分时间都在等待 DNS 响应。所以我的问题是,我怎样才能真正增加使用的线程数?
我已经在三个环境中尝试过该程序;这些是操作系统报告的线程数。
- Java SE 运行时环境在运行 Windows 7 的 8 核机器上构建 1.8.0_73-b02:17 个线程
- Java SE 运行时环境在运行 OS X Darwin 15.2.0 的 2 核机器上构建 1.8.0_66-b17:23 个线程
- 在运行 FreeBSD 11.0 的 24 核机器上的 openjdk 版本 1.8.0_72:44 个线程
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ForkJoinPool;
/** Resolve IP addresses in file args[0] using 100 threads */
public class Resolve100 {
/** Resolve the passed IP address into a name */
static String addressName(String ipAddress) {
try {
return InetAddress.getByName(ipAddress).getHostName();
} catch (UnknownHostException e) {
return ipAddress;
}
}
public static void main(String[] args) {
Path path = Paths.get(args[0]);
ForkJoinPool fjp = new ForkJoinPool(100);
try {
fjp.submit(() -> {
try {
Files.lines(path)
.parallel()
.map(line -> addressName(line))
.forEach(System.out::println);
} catch (IOException e) {
System.err.println("Failed: " + e);
}
}).get();
} catch (Exception e) {
System.err.println("Failed: " + e);
}
}
}
【问题讨论】:
-
您应该将
Files.lines()括在try-with-resources 语句中! -
我建议您在尝试对其进行并行处理之前将这些行添加到列表中。当它预先知道有多少条目时,它会做得更好。
标签: java multithreading java-stream forkjoinpool