java 多线程模板基准测试
java multithreading template benchmarking
我正在尝试对将迭代器的每个元素转换为另一个元素的简单 java 应用程序进行多线程处理的不同方式进行基准测试。
以下哪种方式(java 8 个并行流,使用 lambda 运算符的常规多线程)最有效?根据下面的输出,并行流似乎和传统的多线程一样好,对吗?
以下代码的输出(您必须将 alice.txt 替换为另一个文件)是:
153407 30420
time in ms - 4826
153407 30420
time in ms - 37908
153407 30420
time in ms - 37947
153407 30420
time in ms - 4839
public class ParallelProcessingExample {
public static void main(String[] args) throws IOException{
String contents = new String(Files.readAllBytes(
Paths.get("impatient/code/ch2/alice.txt")), StandardCharsets.UTF_8);
List<String> words = Arrays.asList(contents.split("[\P{L}]+"));
long t=System.currentTimeMillis();
Stream<String> wordStream = words.parallelStream().map(x->process(x));
String[] out0=wordStream.toArray(String[]::new);
System.out.println(String.join("-", out0).length()+"\t"+out0.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
wordStream = words.stream().map(x->process(x));
String[] out1=wordStream.toArray(String[]::new);
System.out.println(String.join("-", out1).length()+"\t"+out1.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
String[] out2=new String[words.size()];
for(int j=0;j<words.size();j++){
out2[j]=process(words.get(j));
}
System.out.println(String.join("-", out2).length()+"\t"+out2.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
int n = Runtime.getRuntime().availableProcessors();
String[] out3=new String[words.size()];
try {
ExecutorService pool = Executors.newCachedThreadPool();
for(int i=0;i<n;i++){
int from=i*words.size()/n;
int to=(i+1)*words.size()/n;
pool.submit(() -> {
for(int j=from;j<to;j++){
out3[j]=process(words.get(j));
}
});
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.HOURS);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.join("-", out3).length()+"\t"+out3.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
}
private static String process(String x) {
try {
TimeUnit.NANOSECONDS.sleep(1);
//Thread.sleep(1); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
return x.toUpperCase();
}
}
Java8个并行流可以(一般!)和手动多线程一样好,但也要看具体情况。
你得到 RejectedExecutionException 因为你太早关闭了池:你应该在 for 循环之外调用 pool.shutdown()
Java 8 个并行流的一大优点是您不必担心这些事情。
我正在尝试对将迭代器的每个元素转换为另一个元素的简单 java 应用程序进行多线程处理的不同方式进行基准测试。
以下哪种方式(java 8 个并行流,使用 lambda 运算符的常规多线程)最有效?根据下面的输出,并行流似乎和传统的多线程一样好,对吗?
以下代码的输出(您必须将 alice.txt 替换为另一个文件)是:
153407 30420
time in ms - 4826
153407 30420
time in ms - 37908
153407 30420
time in ms - 37947
153407 30420
time in ms - 4839
public class ParallelProcessingExample {
public static void main(String[] args) throws IOException{
String contents = new String(Files.readAllBytes(
Paths.get("impatient/code/ch2/alice.txt")), StandardCharsets.UTF_8);
List<String> words = Arrays.asList(contents.split("[\P{L}]+"));
long t=System.currentTimeMillis();
Stream<String> wordStream = words.parallelStream().map(x->process(x));
String[] out0=wordStream.toArray(String[]::new);
System.out.println(String.join("-", out0).length()+"\t"+out0.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
wordStream = words.stream().map(x->process(x));
String[] out1=wordStream.toArray(String[]::new);
System.out.println(String.join("-", out1).length()+"\t"+out1.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
String[] out2=new String[words.size()];
for(int j=0;j<words.size();j++){
out2[j]=process(words.get(j));
}
System.out.println(String.join("-", out2).length()+"\t"+out2.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
t=System.currentTimeMillis();
int n = Runtime.getRuntime().availableProcessors();
String[] out3=new String[words.size()];
try {
ExecutorService pool = Executors.newCachedThreadPool();
for(int i=0;i<n;i++){
int from=i*words.size()/n;
int to=(i+1)*words.size()/n;
pool.submit(() -> {
for(int j=from;j<to;j++){
out3[j]=process(words.get(j));
}
});
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.HOURS);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.join("-", out3).length()+"\t"+out3.length);
System.out.println("time in ms - "+(System.currentTimeMillis()-t));
}
private static String process(String x) {
try {
TimeUnit.NANOSECONDS.sleep(1);
//Thread.sleep(1); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
return x.toUpperCase();
}
}
Java8个并行流可以(一般!)和手动多线程一样好,但也要看具体情况。
你得到 RejectedExecutionException 因为你太早关闭了池:你应该在 for 循环之外调用 pool.shutdown()
Java 8 个并行流的一大优点是您不必担心这些事情。