我的节目没有停止

时间:2015-04-28 00:55:16

标签: java multithreading

我写了这个程序来寻找一个新号码。问题是我的程序没有停止。我知道我必须用线程做点什么,但我不知道。

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上课:

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();
        }


     }
    }

3 个答案:

答案 0 :(得分:3)

只要至少有一个非守护程序线程处于活动状态,JVM就不会终止。

所以基本上你有两个选项,一个是mark your processing thread as daemon,所以它不会让Java退出。另一个选择是你实现某种信号机制,这样一个主线程可以在其工作结束时发出所有其他信号停止信号。

在这两种情况下,您都需要确定待处理的工作是否要阻止您的关闭。在您将处理嵌套到各种线程的情况下,您可能希望在排队特殊的“shutdown”元素时使所有队列处理线程终止(保留run()方法)。

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

这是一个允许停止的示例(不完整)可运行:

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);
        }
    }
}

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);
    }
}

这就是你如何使初始线程将足够的LAST元素排入队列以便工作者终止:

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);
    }
}

这当然要求生产者线程NumberGenerator向候选队列添加LAST元素,候选队列将最后一个元素添加到primesQueue,依此类推。

答案 1 :(得分:0)

正如@Eckes所建议的,要发出其他线程停止的信号。您可以检查candidateQueue和primesQueue的大小,并中断正在运行的线程并退出程序。 我做了一些代码更改,现在程序正在退出。如果这有帮助,请告诉我。

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);

}
}

答案 2 :(得分:0)

以下是更新的代码,如果有帮助请告诉我。

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();
                }

            }
        }
    }
}

素数

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);

    }
}