如何通过仅使用单个线程来检查多线程的性能?

How to check performace of Multi Threading over using only a single thread?

我正在研究 Java 多线程并尝试检查多个线程的性能 threads.I 我正在尝试检查多线程是否比单线程更好。 所以,我写了一个代码来限制总和。 当 limit 变大时,它按我预期的方式工作(多线程比单线程快),但当 limit 小到 100000L 时却没有。 这是由于上下文切换吗?下面的代码是否适合检查多线程的性能?

public class MultiThreadingSum {
    long count = 0;
    static long limit = 1000000000L;

    static void compareMultipleThreadToSingleThread(int threadCnt) {
        Runnable r = () -> {
            MultiThreadingSum mts = new MultiThreadingSum();
            long startTime = System.nanoTime();
            while(++mts.count<=limit);
            long endTime = System.nanoTime();
            long estimatedTime = endTime - startTime;
            double seconds = estimatedTime / 1000000000.0;

            System.out.println(Thread.currentThread().getName()+", elapsed time : "+seconds);
        };

        for(int i=0; i<threadCnt; i++) {
            new Thread(r, "multiThread"+i).start();
        }

        Runnable r2 = () -> {
            MultiThreadingSum mts = new MultiThreadingSum();
            long startTime = System.nanoTime();
            while(++mts.count<=limit*threadCnt);
            long endTime = System.nanoTime();
            long estimatedTime = endTime - startTime;
            double seconds = estimatedTime / 1000000000.0;

            System.out.println(Thread.currentThread().getName()+", elapsed time : "+seconds);
        };

        new Thread(r2, "singleThread").start();
    }

    public static void main(String[] args) {
        compareMultipleThreadToSingleThread(3);
    }
}

这不是一个很好的例子。多线程和单线程解决方案 运行 同时在同一个柜台上。所以实际上你 运行 一个有四个线程的多线程进程。您需要 运行 一个解决方案,直到线程完成并关闭,然后是另一个。最简单的解决方案是 运行 单线程进程作为 main 方法中的简单循环,运行 循环完成后的多线程解决方案。另外,我会有两个单独的计数器,或者,您可以在单线程循环完成后将零分配给计数器

您的代码不会在 运行 单线程实验之前等待 3 线程实验完成。所以你可能会污染你的结果。

您的代码似乎不必要地复杂。我们不能 运行 两个单独的实验,一个有 3 个线程,一个有 1 个线程,分别重用代码吗?

在现代 Java 中,我们很少需要解决 Thread class。相反,使用添加到 Java 5.

的执行程序服务框架

综上所述,也许您的实验应该更像下面这样。

警告:这只是一个非常粗略的剪辑,我没有考虑清楚,我的咖啡因已经耗尽。因此,请深思熟虑地修改此代码。也许我可以在一两天内修改这段代码。

package work.basil.threading;

import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Loopy
{
    public static void main ( String[] args )
    {
        Loopy app = new Loopy();

        List < Integer > inputThreadsLimit = List.of( 1 , 3 , ( Runtime.getRuntime().availableProcessors() - 1 ) );
        for ( Integer numberOfThreads : inputThreadsLimit )
        {
            System.out.println("----------|  Experiment for thread count: " + numberOfThreads + "  |--------------------------");
            Duration duration = app.demo( numberOfThreads ); // Waits here for the experiment to run to completion.
            System.out.println( numberOfThreads + " = " + duration + " total, each: " + duration.dividedBy( numberOfThreads ) );
        }
    }

    // Member fields
    final private AtomicInteger count = new AtomicInteger( 0 );

    private Duration demo ( final int numberOfThreads )
    {
        ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads );
        long start = System.nanoTime();
        for ( int i = 0 ; i < numberOfThreads ; i++ )
        {
            executorService.submit( new Task() );
        }
        executorService.shutdown();  // Ask the executor service to shutdown its backing pool of threads after all submitted tasks are done/canceled/failed.
        try { executorService.awaitTermination( 1 , TimeUnit.HOURS ); } catch ( InterruptedException e ) { e.printStackTrace(); } // Tries to force the shutdown after timeout.

        Duration elapsed = Duration.ofNanos( System.nanoTime() - start );
        return elapsed;
    }

    class Task implements Runnable
    {
        @Override
        public void run ( )
        {
            int countSoFar = count.incrementAndGet();  // Thread-safe way to access, increment, and write a counter.
            // … add code here to do some kind of work …
            System.out.println( "Thread ID " + Thread.currentThread().getId() + " is finishing run after incrementing the countSoFar to: " + countSoFar + " at " + Instant.now() );
        }
    }
}