使用ExecutorService的Consumer / Producer卡住了

时间:2016-04-18 10:19:15

标签: java multithreading producer-consumer blockingqueue

我是多线程的新手,我正在尝试编写以下简单程序:

  1. 阅读文件
  2. 将输出打印到屏幕
  3. 我创建了以下类:Consumer

    public class Consumer implements Runnable {
        private BlockingQueue<String> m_Queue;
    
    public Consumer(BlockingQueue<String> i_Queue)
    {
        m_Queue = i_Queue;
    }
    
    @Override
    public void run()
    {
        try
        {
            String referenceID1;
    
            //Consuming message until exit message is received.
            while((referenceID1 = m_Queue.take()) !="EOF")
            {
                System.out.println(referenceID1);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }}
    

    制片:

    public class Producer implements Runnable {
    private BlockingQueue<String> m_Queue;
    private String m_FilePath;
    
    public Producer(BlockingQueue<String> i_Queue, String i_FilePath)
    {
        m_Queue = i_Queue;
        m_FilePath = i_FilePath;
    }
    
    @Override
    public void run()
    {
        try (BufferedReader reader = new BufferedReader(new FileReader(m_FilePath)))
        {
            String line;
            while ((line = reader.readLine()) != null)
            {
                m_Queue.put(line);
                System.out.println(line + " Was added to queue.");
            }
    
            //Adding an exit message.
            m_Queue.put("EOF");
            System.out.println("EOF Was added to queue.");
        }
        catch (IOException | InterruptedException e)
        {
            e.printStackTrace();
        }
    }}
    

    ProducerConsumerService

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
    
        //Start the producer; Will read the file
        threadPool.execute(new Producer(queue, args[0]));
    
        for (int i = 0; i < 4; i++)
        {
            System.out.println("Generating consumer " + i+1);
            threadPool.execute(new Consumer(queue));
        }
    
        try
        {
            threadPool.shutdown();
            System.out.println("Shutting down threads.");
    
            threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            System.out.println("Terminated successfully.");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        } }
    

    输入文件由数字1-20组成,每个数字都在一个新行中。 当我运行程序时,我可以看到所有数字都被读取,但程序似乎挂起/卡住了,我没有看到“已成功终止”消息。
    如果我使用单个线程进行读取而单个线程在屏幕上打印,则不会发生这种情况,但使用1个线程无法满足我对“多线程”程序的需求。
    我的猜测是我忘了发布一个资源,但我不知道为什么。

1 个答案:

答案 0 :(得分:2)

您的问题是您在take()中使用了Consumer

  

检索并删除此队列的头部,必要时等待   直到一个元素可用。

并且您测试返回的值是否为EOF(不正确BTW,您需要使用equals)但是只将其放入队列中并且您有4 Consumer所以3 {{1}还在等待它。

所以你应该使用Consumer代替如下:

poll()

或者只是如果你摆脱while((referenceID1 = m_Queue.poll()) != null && !Objects.equals(referenceID1, "EOF"))

EOF