Aryan
Aryan

Reputation: 23

My program doesn't stop

I wrote this program for finding a new number. The problem is my program doesn't stop. I know I have to do something with threads but I don't what.

Primes class (main):

public class Primes {

  /** 
   * The queue holding candidates we want to check for primality.
   */
  private BlockingQueue<Integer> candidateQueue;

  /** 
   * The queue holding primes we want to print before inserting into the result set.
   */
  private BlockingQueue<Integer> primesQueue;

  /**
   * The set holding the numbers that we have determined are prime.
   */
  private Set<Integer> primeNumbers;

  /**
   * Create a new instance of the Primes checker program.
   */
  public Primes() {
    // TODO: If this the best type of BlockingQueue to use, and is this the best size?
    // Feel free to change both.
    candidateQueue = new LinkedBlockingQueue<Integer>();

    // TODO: If this the best type of BlockingQueue to use, and is this the best size?
    // Feel free to change both.
    primesQueue = new LinkedBlockingQueue<Integer>();

    // TODO: Is a HashSet the best option here, and are there any options that would
    // help make it perform better? Feel free to change to a different type of Set or
    // to add parameters to the constructor.
    primeNumbers = new HashSet<Integer>();
  }

  /**
   * Actually run the primes finder, looking for primes between smallest and biggest (inclusive).
   * 
   * @param smallest the smallest number to check
   * @param biggest the biggest number to check
   * 
   * @return a {@link Set} containing the prime numbers we have found
   */
  public Set<Integer> findPrimesInRange(int smallest, int biggest) {
    // TODO: You should create the number generator and primes printer, as well
    // as some number of primality checkers. You should create these all as
    // threads that you can run to look for prime numbers. You should have at least
    // two instances of {@link PrimalityChecker}, but could have more if this makes
    // your program faster.

    // TODO: This is just here to make the compiler happy, you should return something real...
        NumberGenerator a = new NumberGenerator( smallest,biggest,candidateQueue);
        new Thread(a).start();
        PrimalityChecker p1 = new PrimalityChecker(candidateQueue,primesQueue);
        new Thread(p1).start();
        PrimalityChecker p2 = new PrimalityChecker(candidateQueue,primesQueue);
        new Thread(p2).start();
        PrimesPrinter pp = new PrimesPrinter(primesQueue,primeNumbers);
       Thread t1= new Thread(pp);
        t1.start();
       // t1.interrupt();






    return primeNumbers;
  }

  public static void main(String[] args) {
    Primes p = new Primes();
    // Remember, 1 is not prime! http://en.wikipedia.org/wiki/Prime_number
    p.findPrimesInRange(2, 100);
  }
}

NumberGenerator class:

public class NumberGenerator implements Runnable {
  /** The biggest number we plan to check */
  private final int biggestNumberToCheck;

  /** A queue where we will place the numbers that we generate, which need to be checked */
  private final BlockingQueue<Integer> candidateQueue;
  private final int smallestNumberStart;

  // TODO: What other state do we need?

  /**
   * Create a new instance of the NumberGenerator class, which will hand out numbers
   * that need to be checked.
   * 
   * @param smallest the smallest number to check
   * @param biggest the biggest number to check
   * @param queue the queue that we will put numbers to check into
   */
  public NumberGenerator(int smallest, int biggest, BlockingQueue<Integer> queue) {
    biggestNumberToCheck = biggest;
    candidateQueue = queue;
    smallestNumberStart = smallest;
  }
  public void run(){
    for(int i=smallestNumberStart; i<=biggestNumberToCheck; i++){
    //int rand= ThreadLocalRandom.current().nextInt(smallestNumberStart, biggestNumberToCheck);
    candidateQueue.add(i);
    }

  }
  // TODO: You can decide how you want to turn this into something runnable as a thread.
  // Please look at the code examples we've discussed in class and at the lecture slides,
  // as well as at the Concurrency tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/
}

PrimalityChecker:

public class PrimalityChecker implements Runnable {
  /** A queue that holds generated numbers that we have not yet checked */
  private final BlockingQueue<Integer> candidateQueue;

  /** A queue where we place numbers when we determine they are prime */
  private final BlockingQueue<Integer> primesQueue;

  // TODO: What other state do we need?

  /**
   * Create an instance of the PrimalityChecker class, which will check numbers to see if
   * they are prime and then insert them into a result queue.
   * 
   * @param candidates queue that holds the candidates to check
   * @param primes queue that holds prime numbers we have found
   */
  public PrimalityChecker(BlockingQueue<Integer> candidates, BlockingQueue<Integer> primes) {
    candidateQueue = candidates;
    primesQueue = primes;
  }
  public void run(){






         Iterator<Integer> itr = candidateQueue.iterator();

        while(itr.hasNext()){
        Integer Queue = null;
        try {
          Queue = candidateQueue.take();
        } catch (InterruptedException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
        } 
        if (isPrime(Queue))
        {
             primesQueue.add(Queue);
            // try {
              // System.out.println(primesQueue.take());
            // } catch (InterruptedException e) {
                // TODO Auto-generated catch block
              // e.printStackTrace();
              //}

           }
        }

         //catch (InterruptedException e) {
          // TODO Auto-generated catch block
        // e.printStackTrace();
        //}
    //

  }
   public static boolean isPrime(int number){
          for(int i=2; i<number; i++){
              if(number%i == 0){
                  return false; 
              }
          }
          return true; 
      }
  // TODO: You can decide how you want to turn this into something runnable as a thread.
  // Please look at the code examples we've discussed in class and at the lecture slides,
  // as well as at the Concurrency tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/
}

PrimePrinter:

public class PrimesPrinter implements Runnable {
  /** A queue that holds numbers we have determined to be prime but have not yet processed */
  private final BlockingQueue<Integer> primesQueue;

  /** A set that holds all the prime numbers we have found */
  private final Set<Integer> primesSet;

  // TODO: What other state do we need?

  /**
   * Create an instance of the PrimesPrinter class, which will print any numbers that
   * come in on the primes queue and then place them in the primes set.
   * 
   * @param primes queue that holds prime numbers we have found but not yet processed
   * @param primesSet set that holds all the prime numbers we have found
   */
  public PrimesPrinter(BlockingQueue<Integer> primes, Set<Integer> primesSet) {
    primesQueue = primes;
    this.primesSet = primesSet;
  }

  @Override
  public void run() {
    // Iterator<Integer> itr = primesQueue.iterator();
  // while (!Thread.currentThread().isInterrupted()){
            while(primesQueue.size()>=0){
              Integer Queue;
        try {
          Queue=primesQueue.take();
          //Queue = primesQueue.poll(100, TimeUnit.MILLISECONDS);
          //if(Queue==null){

          // break;
          //}
          System.out.println(Queue);

          primesSet.add(Queue);
        }

        catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }


     }
    }

Upvotes: 1

Views: 117

Answers (3)

eckes
eckes

Reputation: 10423

A JVM does not terminate as long as there is at least one non-daemon thread alive.

So basically you have two options, one would be to mark your processing thread as daemon, so it wont keep Java from exiting. The other option is you implement some kind of signalling mechanism so a main thread can at the end of its work signal all others to stop.

In both cases you need to decide if pending work wants to hold up your shut-down or not. In your case where you nest the processing over various threads you might want to make all the queue processing threads terminate (leave the run() method) when you enqueue a special "shutdown" element.

// this is how you start a runable with a daemon thread
Thread t1 = new Thread(r1);
t1.setDaemon(true);
t1.start();

And here is a sample (incomplete) runable which allows to be stopped:

public class PrimesPrinter implements Runnable {
    public static final Integer LAST = new Integer(0); // values doesnt matter
    private final BlockingQueue<Integer> primesQueue;
    private int lastCount = 0;

    public void run() {
        while (true) {
          Integer i = primesQueue.take(); // blocks
          if (i == LAST) {
              lastCount++; // wait for 2 checkers
              if (lastCount == 2)
                return;
              else
                continue; // next might be last or other result
          }
          System.out.println(i);
        }
    }
}

and

public class PrimalityChecker implements Runnable {
    public static final Integer LAST = new Integer(42);
    public void run() {
        while (true) {
            Integer i = candidateQueue.take();
            if (i == PrimalityChecker.LAST) break;
            if (isPrime(Queue))
                primesQueue.add(Queue);
        }
        primesQueue.add(PrimesPrinter.LAST);
    }
}

And this is how you make the initial thread enqueue enough LAST elements so the worker terminate:

public NumberGenerator(int smallest, int biggest, BlockingQueue<Integer> queue) {
    public void run(){
        for(int i=smallestNumberStart; i<=biggestNumberToCheck; i++){
            candidateQueue.add(i);
        }
        candidateQueue.add(PrimalityChecker.LAST);
        candidateQueue.add(PrimalityChecker.LAST);
    }
}

This of course expects the producer threads NumberGenerator to add a LAST element to the candidate queue, the candidate queue to add a last element to the primesQueue and so on.

Upvotes: 3

Sunil Rajashekar
Sunil Rajashekar

Reputation: 350

Below is updated code, let me know if it helps.

import java.util.concurrent.BlockingQueue;

public class NumberGenerator implements Runnable {
    private final int biggestNumberToCheck;
    private final BlockingQueue<Integer> candidateQueue;
    private final int smallestNumberStart;

    public NumberGenerator(int smallest, int biggest,
            BlockingQueue<Integer> queue) {
        biggestNumberToCheck = biggest;
        candidateQueue = queue;
        smallestNumberStart = smallest;
    }

    public void run() {
        for (int i = smallestNumberStart; i <= biggestNumberToCheck; i++) {
            candidateQueue.add(i);
        }

    }
}

PrimalityChecker

import java.util.Iterator;
import java.util.concurrent.BlockingQueue;

public class PrimalityChecker implements Runnable {
    private final BlockingQueue<Integer> candidateQueue;

    private final BlockingQueue<Integer> primesQueue;

    public PrimalityChecker(BlockingQueue<Integer> candidates,
            BlockingQueue<Integer> primes) {
        candidateQueue = candidates;
        primesQueue = primes;
    }

    public void run() {
        Iterator<Integer> itr = candidateQueue.iterator();

        while (itr.hasNext()) {
            Integer Queue = null;
            try {
                Queue = candidateQueue.take();
            } catch (InterruptedException e1) {
                System.out.println("PrimalityChecker Thread interruped");
                return;
            }
            if (isPrime(Queue)) {
                primesQueue.add(Queue);

            }
        }

    }

    public static boolean isPrime(int number) {
        for (int i = 2; i < number; i++) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }

}

PrimesPrinter

import java.util.Set;
import java.util.concurrent.BlockingQueue;

public class PrimesPrinter implements Runnable {
    private final BlockingQueue<Integer> primesQueue;

    private final Set<Integer> primesSet;

    public PrimesPrinter(BlockingQueue<Integer> primes, Set<Integer> primesSet) {
        primesQueue = primes;
        this.primesSet = primesSet;
    }

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            while (primesQueue.size() > 0) {
                Integer Queue;
                try {
                    Queue = primesQueue.take();
                    System.out.println(Queue);

                    primesSet.add(Queue);
                }

                catch (InterruptedException e) {
                    System.out.println("Primes Printer Interrupted");
                    e.printStackTrace();
                }

            }
        }
    }
}

Primes

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Primes {

    private BlockingQueue<Integer> candidateQueue;

    private BlockingQueue<Integer> primesQueue;

    private Set<Integer> primeNumbers;

    public Primes() {
        candidateQueue = new LinkedBlockingQueue<Integer>();
        primesQueue = new LinkedBlockingQueue<Integer>();
        primeNumbers = new HashSet<Integer>();
    }

    public void findPrimesInRange(int smallest, int biggest) {

        NumberGenerator a = new NumberGenerator(smallest, biggest,
                candidateQueue);
        Thread threadA = new Thread(a);
        threadA.start();

        PrimalityChecker p1 = new PrimalityChecker(candidateQueue, primesQueue);
        Thread threadP1 = new Thread(p1);
        threadP1.start();

        PrimalityChecker p2 = new PrimalityChecker(candidateQueue, primesQueue);
        Thread threadP2 = new Thread(p2);
        threadP2.start();

        PrimesPrinter pp = new PrimesPrinter(primesQueue, primeNumbers);
        Thread threadPP = new Thread(pp);
        threadPP.start();

        while (true) {
            try {
                Thread.sleep(1000);
                if (candidateQueue.size() == 0 && primesQueue.size() == 0) {
                    threadA.interrupt();
                    threadP1.interrupt();
                    threadP2.interrupt();
                    threadPP.interrupt();
                    break;

                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Primes p = new Primes();
        p.findPrimesInRange(2, 100);

    }
}

Upvotes: 0

Sunil Rajashekar
Sunil Rajashekar

Reputation: 350

As suggested by @Eckes, to signal the other threads to stop. You can check the size of candidateQueue and primesQueue and interrupt the running threads and exit the program. I made some code changes and now the program is exiting. Let me know if this helps.

import java.util.concurrent.BlockingQueue;

public class NumberGenerator implements Runnable {
/** The biggest number we plan to check */
private final int biggestNumberToCheck;

/** A queue where we will place the numbers that we generate, which need to be checked */
private final BlockingQueue<Integer> candidateQueue;
private final int smallestNumberStart;

// TODO: What other state do we need?

/**
 * Create a new instance of the NumberGenerator class, which will hand out numbers
 * that need to be checked.
 * 
 * @param smallest the smallest number to check
 * @param biggest the biggest number to check
 * @param queue the queue that we will put numbers to check into
 */
public NumberGenerator(int smallest, int biggest, BlockingQueue<Integer> queue) {
    biggestNumberToCheck = biggest;
    candidateQueue = queue;
    smallestNumberStart = smallest;
}
public void run(){
    for(int i=smallestNumberStart; i<=biggestNumberToCheck; i++){
    //int rand= ThreadLocalRandom.current().nextInt(smallestNumberStart, biggestNumberToCheck);
    candidateQueue.add(i);
    }

}
// TODO: You can decide how you want to turn this into something runnable as a thread.
// Please look at the code examples we've discussed in class and at the lecture slides,
// as well as at the Concurrency tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/
}





import java.util.Iterator;
import java.util.concurrent.BlockingQueue;

public class PrimalityChecker implements Runnable {
/** A queue that holds generated numbers that we have not yet checked */
private final BlockingQueue<Integer> candidateQueue;

/** A queue where we place numbers when we determine they are prime */
private final BlockingQueue<Integer> primesQueue;

// TODO: What other state do we need?

/**
 * Create an instance of the PrimalityChecker class, which will check numbers to see if
 * they are prime and then insert them into a result queue.
 * 
 * @param candidates queue that holds the candidates to check
 * @param primes queue that holds prime numbers we have found
 */
public PrimalityChecker(BlockingQueue<Integer> candidates, BlockingQueue<Integer> primes) {
    candidateQueue = candidates;
    primesQueue = primes;
}

    public void run() {
        Iterator<Integer> itr = candidateQueue.iterator();

        while (itr.hasNext()) {
            Integer Queue = null;
            try {
                Queue = candidateQueue.take();
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                return;
            }
            if (isPrime(Queue)) {
                primesQueue.add(Queue);
                // try {
                // System.out.println(primesQueue.take());
                // } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                // }

            }
        }

        // catch (InterruptedException e) {
        // TODO Auto-generated catch block
        // e.printStackTrace();
        // }
        //

    }
 public static boolean isPrime(int number){
        for(int i=2; i<number; i++){
            if(number%i == 0){
                return false; 
            }
        }
        return true; 
    }
// TODO: You can decide how you want to turn this into something runnable as a thread.
// Please look at the code examples we've discussed in class and at the lecture slides,
// as well as at the Concurrency tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/
}



import java.util.Set;
import java.util.concurrent.BlockingQueue;

public class PrimesPrinter implements Runnable {
/** A queue that holds numbers we have determined to be prime but have not yet processed */
private final BlockingQueue<Integer> primesQueue;

/** A set that holds all the prime numbers we have found */
private final Set<Integer> primesSet;

// TODO: What other state do we need?

/**
 * Create an instance of the PrimesPrinter class, which will print any numbers that
 * come in on the primes queue and then place them in the primes set.
 * 
 * @param primes queue that holds prime numbers we have found but not yet processed
 * @param primesSet set that holds all the prime numbers we have found
 */
public PrimesPrinter(BlockingQueue<Integer> primes, Set<Integer> primesSet) {
    primesQueue = primes;
    this.primesSet = primesSet;
}

@Override
    public void run() {
        // Iterator<Integer> itr = primesQueue.iterator();
        while (!Thread.currentThread().isInterrupted()) {
            while (primesQueue.size() > 0) {
                Integer Queue;
                try {
                    Queue = primesQueue.take();
                    // Queue = primesQueue.poll(100, TimeUnit.MILLISECONDS);
                    // if(Queue==null){

                    // break;
                    // }
                    System.out.println(Queue);

                    primesSet.add(Queue);
                }

                catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
    }
}


import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Primes {

/** 
 * The queue holding candidates we want to check for primality.
 */
private BlockingQueue<Integer> candidateQueue;

/** 
 * The queue holding primes we want to print before inserting into the result set.
 */
private BlockingQueue<Integer> primesQueue;

/**
 * The set holding the numbers that we have determined are prime.
 */
private Set<Integer> primeNumbers;

/**
 * Create a new instance of the Primes checker program.
 */
public Primes() {
    // TODO: If this the best type of BlockingQueue to use, and is this the best size?
    // Feel free to change both.
    candidateQueue = new LinkedBlockingQueue<Integer>();

    // TODO: If this the best type of BlockingQueue to use, and is this the best size?
    // Feel free to change both.
    primesQueue = new LinkedBlockingQueue<Integer>();

    // TODO: Is a HashSet the best option here, and are there any options that would
    // help make it perform better? Feel free to change to a different type of Set or
    // to add parameters to the constructor.
    primeNumbers = new HashSet<Integer>();
}

/**
 * Actually run the primes finder, looking for primes between smallest and biggest (inclusive).
 * 
 * @param smallest the smallest number to check
 * @param biggest the biggest number to check
 */
public void findPrimesInRange(int smallest, int biggest) {
    // TODO: You should create the number generator and primes printer, as well
    // as some number of primality checkers. You should create these all as
    // threads that you can run to look for prime numbers. You should have at least
    // two instances of {@link PrimalityChecker}, but could have more if this makes
    // your program faster.

    // TODO: This is just here to make the compiler happy, you should return something real...
    NumberGenerator a = new NumberGenerator( smallest,biggest,candidateQueue);
    Thread threadA= new Thread(a);
    threadA.start();

    PrimalityChecker p1 = new PrimalityChecker(candidateQueue,primesQueue);
    Thread threadP1= new Thread(p1);
    threadP1.start();

    PrimalityChecker p2 = new PrimalityChecker(candidateQueue,primesQueue);
    Thread threadP2= new Thread(p2);
    threadP2.start();

    PrimesPrinter pp = new PrimesPrinter(primesQueue,primeNumbers);
    Thread threadPP= new Thread(pp);
    threadPP.start();


    while(true){
        try {
            Thread.sleep(1000);
            if(candidateQueue.size() == 0 && primesQueue.size() ==0){
                threadA.interrupt();
                threadP1.interrupt();
                threadP2.interrupt();
                threadPP.interrupt();
                break;

            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

   // t1.interrupt();

    //System.out.println("T");

}

public static void main(String[] args) {
    Primes p = new Primes();
    // Remember, 1 is not prime! http://en.wikipedia.org/wiki/Prime_number
    p.findPrimesInRange(2, 100);

}
}

Upvotes: 0

Related Questions