Home » Java » multithreading – Parallel prime number checker using threads in Java-Exceptionshub

multithreading – Parallel prime number checker using threads in Java-Exceptionshub

Posted by: admin February 23, 2020 Leave a comment

Questions:

I have a java program that checks if numbers are prime. I tried to make it parallel by checking different numbers using separate threads.

I ran the programs and compared their execution times, but I am not seeing an improvement…

Here is my sequential program, 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));

                // boolean isPrime = isPrime(Long.parseLong(args[i]));
                // System.out.println(args[i] + ": " + isPrime);
            }

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

And here is my attempt at parallelizing it, 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++)
            {
                try
                {
                    Thread newThread = new MyThread(args[i]);
                    newThread.start();
                    newThread.join();
                }
                catch (InterruptedException exc)
                {
                    System.out.println(exc); 
                }
            }

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

Here is the output of these:

PrimeSeq:

$ 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
1000000000000037: true  Start time: 143746202   End time: 143746309 Elapsed time: 107
1000000000000091: true  Start time: 143746310   End time: 143746415 Elapsed time: 105
1000000000000159: true  Start time: 143746415   End time: 143746519 Elapsed time: 104
1000000000000187: true  Start time: 143746520   End time: 143746619 Elapsed time: 99
Total time: 418 milliseconds

It doesn’t seem that my parallel program is actually running in parallel. How can I fix this?

How to&Answers:

As pointed out by user “Dawood says reinstate Monica” in the comments, newThread.join() was the problematic command.

Removing this helps, as all the threads start at the same time:

Updated primePar.java program:

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++)
            {
                // try
                // {
                    Thread newThread = new MyThread(args[i]);
                    newThread.start();
                    // newThread.join();
                // }
                // catch (InterruptedException exc)
                // {
                //  System.out.println(exc); 
                // }
            }

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

New output:

$ 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