2016-07-29 139 views
0

我指的是BlockingQue的概念,我找到一个示例hereBlockingQueue程序不会退出

import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; /* j a v a 2s . co m*/ 
public class Main { 
    public static void main(String[] argv) throws Exception { 
     int capacity = 10; 
     BlockingQueue <Integer> queue = new ArrayBlockingQueue <Integer> (capacity); 

     int numWorkers = 2; 
     Worker[] workers = new Worker[numWorkers]; 
     for (int i = 0; i < workers.length; i++) { 
      workers[i] = new Worker(queue); 
      workers[i].start(); 
     } 

     for (int i = 0; i < 10; i++) { 
      queue.put(i); 
     } 
    } 
} 

class Worker extends Thread { 
    BlockingQueue <Integer> q; 

    Worker(BlockingQueue <Integer> q) { 
     this.q = q; 
    } 

    public void run() { 
     try { 
      while (true) { 
       Integer x = q.take(); 
       if (x == null) { 
        break; 
       } 
       System.out.println(x); 
      } 
     } catch (InterruptedException e) {} 
    } 
} 

在这个例子中,他们只使用了一个工作线程的线程。

我对BlockingQue的理解是,它是生产者 - 消费者模式的替代解决方案。

所以我们需要两个线程来处理。因此我有疑问/问题。

以下是我的问题。

  1. 他们使用主线程作为另一个线程吗?

  2. 当我运行该应用程序时,程序不会退出。我不明白主程序为什么不退出?

回答

0

回答1不,他们没有使用主线程的其他任何东西。主线完美地退出。

回答2.在所有非守护进程线程结束之前,JVM不会退出。 (来源:http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

如果您希望JVM在主线程完成后退出,请在您的for循环中添加workers[i].setDaemon(true);以使您的工作线程进入守护线程。

你的非守护线程不存在的原因是你有Integer x = q.take();在Worker的run方法的循环中。因此这些工作线程永远在等待新的整数被放入队列中。

建议:您可以使用Eclipse的Java IDE调试和看到最新实际上将每个线程

1

上。在您提到的示例代码中,你有一个监制Main线程)和两个消费者Worker主题)。

在生产者 - 消费者问题中,没有必要只有一个生产者和只有一个消费者 - 你可以有多个生产者和多个消费者。他们的相对数量通常决定谁正在做更复杂和更耗时的任务。

答1:主线程是生产者线程,因为它是被用来放物品BlockingQueuequeue.put(i)

答2:把十个元素后,你的主线程退出排队,但你的工人线程不断等待元素(即使消耗了10个元素),因为q.take()是一种阻塞方法,即它等待要投入更多的元素来排队(当queue为空)

解决方案:你需要放两个EOF元/ ObjectsEND OF FILE)排队,做检查像你这样,if (x == null)。尝试在队列中添加两个额外的空值,以便当您的工作/消费者线程找到它时,它们将终止。目前,您的条件if (x == null)永远不会被满足。