首页 > 解决方案 > 跟踪多线程java程序的总执行时间

问题描述

我有一个检查数字是否为素数的 java 程序。我试图通过使用单独的线程检查不同的数字来使其并行。

这是我的顺序程序 primeSeq.java:

import java.io.*;
import java.text.ParseException;
import java.util.concurrent.TimeUnit;
import java.lang.Object;

class primeSeq {

    static boolean isPrime(long n) {
        // Check base cases:
        // n < 2, n is 2 or 3, n is divisible by 2 or 3
        if(n < 2) return false;
        if(n == 2 || n == 3) return true;
        if(n%2 == 0 || n%3 == 0) return false;

        // Check if divisible by all numbers 6k +-1 up to sqrt(n)
        long sqrtN = (long)Math.sqrt(n)+1;
        for(long i = 6L; i <= sqrtN; i += 6) {
            if(n%(i-1) == 0 || n%(i+1) == 0) return false;
        }
        return true;
    }

    public static void main(String args[]) throws ParseException
    {
        if (args.length == 0){
            System.out.println("No args provided.");
        }
        else
        {
            long startTime = System.nanoTime();

            for(int i=0;i< args.length;i++)
            {
                long single_startTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
                boolean isPrime = isPrime(Long.parseLong(args[i]));
                long single_endTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
                System.out.println(args[i] + ": " + isPrime + "\tStart time: " + single_startTime + "\tEnd time: " + single_endTime + "\tElapsed time: " + (single_endTime - single_startTime));

            }

            long endTime = System.nanoTime();
            System.out.println("Total time: " + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + " milliseconds");
        }
    }
}

这是我并行化它的尝试,primePar.java:

import java.io.*;
import java.text.ParseException;
import java.util.concurrent.TimeUnit;
import java.lang.Object;

class MyThread extends Thread
{
    boolean isPrime(long n) {
        // Check base cases:
        // n < 2, n is 2 or 3, n is divisible by 2 or 3
        if(n < 2) return false;
        if(n == 2 || n == 3) return true;
        if(n%2 == 0 || n%3 == 0) return false;

        // Check if divisible by all numbers 6k +-1 up to sqrt(n)
        long sqrtN = (long)Math.sqrt(n)+1;
        for(long i = 6L; i <= sqrtN; i += 6) {
            if(n%(i-1) == 0 || n%(i+1) == 0) return false;
        }
        return true;
    }

    String threadName;
    public MyThread(String threadName)
    {
        super(threadName);
        this.threadName = threadName;
    }

    @Override
    public void run()
    {
        long startTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
        boolean isPrime = isPrime(Long.parseLong(threadName));
        long endTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
        System.out.println(threadName + ": " + isPrime + "\tStart time: " + startTime + "\tEnd time: " + endTime + "\tElapsed time: " + (endTime - startTime));
    }
}

class primePar {
    public static void main(String args[]) throws ParseException
    {
        if (args.length == 0){
            System.out.println("No args provided.");
        }
        else
        {
            long startTime = System.nanoTime();

            for(int i=0;i< args.length;i++)
            {

                Thread newThread = new MyThread(args[i]);
                newThread.start();
            }

            long endTime = System.nanoTime();
            System.out.println("Total time: " + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + " milliseconds");
        }
    }
}

以下是这些的输出:

素序列:

$ java primeSeq 1000000000000037 1000000000000091 1000000000000159 1000000000000187
1000000000000037: true  Start time: 143773080   End time: 143773182 Elapsed time: 102
1000000000000091: true  Start time: 143773183   End time: 143773284 Elapsed time: 101
1000000000000159: true  Start time: 143773284   End time: 143773400 Elapsed time: 116
1000000000000187: true  Start time: 143773400   End time: 143773510 Elapsed time: 110
Total time: 430 milliseconds

PrimePar:

$ java primePar 1000000000000037 1000000000000091 1000000000000159 1000000000000187
Total time: 0 milliseconds
1000000000000091: true  Start time: 144449191   End time: 144449354 Elapsed time: 163
1000000000000159: true  Start time: 144449191   End time: 144449355 Elapsed time: 164
1000000000000187: true  Start time: 144449191   End time: 144449357 Elapsed time: 166
1000000000000037: true  Start time: 144449191   End time: 144449370 Elapsed time: 179

由于所有线程同时启动,因此我的并行程序似乎运行正常。但是,总执行时间不是我想要的(它说 0 毫秒)。如何更改它以跟踪所有线程完成所需的总执行时间(对于上述输出,它将是 179 毫秒)?

标签: javamultithreading

解决方案


如果您想要整个程序的执行时间,您的主线程必须等待其他线程完成才能计算。这是0 milliseconds因为在创建并启动线程后,主线程会立即进入最终打印,而您的线程仍在后台运行。

在这种情况下,您需要收集您拥有的线程,然后调用join()它们。此方法告诉发生调用的线程(在本例中为主线程)等待您调用该方法的线程在继续之前终止。通过这样做,您将确保所有线程在主线程继续计算总执行时间之前完成计算。

像这样的东西应该工作:

long startTime = System.nanoTime();

List<Thread> threads = new ArrayList<>();

for(int i=0;i< args.length;i++)
{

    Thread newThread = new MyThread(args[i]);
    newThread.start();
    threads.add(newThread);
}

threads.forEach(t -> {
    try {
        t.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

long endTime = System.nanoTime();
System.out.println("Total time: " + TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + " milliseconds");

这里查看更多信息。


推荐阅读