java多线程模板基准测试

标签 java multithreading lambda java-8 java-stream

我正在尝试对将迭代器的每个元素转换为另一个元素的简单 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();
}

}

最佳答案

Java 8 并行流可以(通常!)与手动多线程一样好,但这也取决于具体情况。

你得到 RejectedExecutionException 因为你太早关闭了池:你应该在 for 循环之外调用 pool.shutdown()

Java 8 并行流的一大优势是您不必担心此类事情。

关于java多线程模板基准测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28246764/

相关文章:

multithreading - Jersey ContainerResponseFilter 中的@Context HttpServletRequest 范围

c# - 当 ThreadPool WaitCallback 在关闭后调用 Form 时,Form 会发生什么情况?

c# - Linq 和异步 Lambda

java - 如何测试异步方法

java - java中如何判断一个类是否是接口(interface)的实现

Java8 代码无法在 IntelliJ IDEA 中解析

java - 如何从 Quickblox 中的消息中检索用户名?

c++ - 从这个对象的方法开始的线程中销毁类对象的最佳实践

python - 对两个 NumPy 数组中的正元素和负元素求和

c# - 如何为 EF Core 创建可重用的 'Contains' 表达式