Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有ExecutorService的消费者/生产者被卡住_Java_Multithreading_Producer Consumer_Blockingqueue - Fatal编程技术网

Java 具有ExecutorService的消费者/生产者被卡住

Java 具有ExecutorService的消费者/生产者被卡住,java,multithreading,producer-consumer,blockingqueue,Java,Multithreading,Producer Consumer,Blockingqueue,我是多线程新手,正在尝试编写以下简单程序: 读文件 将输出打印到屏幕上 我创建了以下类:Consumer public class Consumer implements Runnable { private BlockingQueue<String> m_Queue; public Consumer(BlockingQueue<String> i_Queue) { m_Queue = i_Queue; } @Override public void

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

  • 读文件
  • 将输出打印到屏幕上
  • 我创建了以下类: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();
        }
    }}
    
    公共类使用者实现可运行{
    私有阻塞队列;
    公共消费者(封锁队列i_队列)
    {
    m_队列=i_队列;
    }
    @凌驾
    公开募捐
    {
    尝试
    {
    字符串引用1;
    //在收到退出消息之前一直使用消息。
    而((referenceID1=m_Queue.take())!=“EOF”)
    {
    系统输出打印项次(参考1);
    }
    }
    捕获(例外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();
        }
    }}
    
    公共类生成器实现可运行{
    私有阻塞队列;
    私有字符串m_FilePath;
    公共生产者(阻塞队列i_队列、字符串i_文件路径)
    {
    m_队列=i_队列;
    m_FilePath=i_FilePath;
    }
    @凌驾
    公开募捐
    {
    try(BufferedReader=new BufferedReader(new FileReader(m_FilePath)))
    {
    弦线;
    而((line=reader.readLine())!=null)
    {
    m_Queue.put(行);
    System.out.println(第+“行被添加到队列。”);
    }
    //添加退出消息。
    m_Queue.put(“EOF”);
    System.out.println(“EOF已添加到队列。”);
    }
    捕获(IOException | InterruptedException e)
    {
    e、 printStackTrace();
    }
    }}
    
    生产消费服务

    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();
        } }
    
    publicstaticvoidmain(字符串[]args){
    ExecutorService线程池=Executors.newFixedThreadPool(5);
    BlockingQueue=new ArrayBlockingQueue(100);
    //启动生产者;将读取文件
    execute(新生产者(队列,参数[0]);
    对于(int i=0;i<4;i++)
    {
    System.out.println(“生成用户”+i+1);
    执行(新使用者(队列));
    }
    尝试
    {
    threadPool.shutdown();
    System.out.println(“关闭线程”);
    线程池终止(Long.MAX_值,时间单位纳秒);
    System.out.println(“成功终止”);
    }
    捕捉(中断异常e)
    {
    e、 printStackTrace();
    } }
    
    输入文件由数字1-20组成,每个数字在新行中。 当我运行程序时,我可以看到所有的数字都被读取,但程序似乎挂起/卡住了,我没有看到“已成功终止”消息。
    如果我使用一个线程进行阅读,一个线程用于在屏幕上打印,则不会发生这种情况,但使用一个线程无法满足我对“多线程”程序的需求

    我猜我忘了释放资源,但我不知道为什么。

    您的问题是在
    消费者中使用
    take()
    ,其中:

    检索并删除此队列的头,如有必要,请等待 直到某个元素可用为止

    您可以测试返回值是否为
    EOF
    (顺便说一句,您需要使用equals),但您只将其放入队列一次,就有4个
    消费者
    ,所以3个
    消费者仍在等待它

    因此,您应该使用
    poll()
    ,如下所示:

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

    while((referenceID1 = m_Queue.poll()) != null)
    

    请替换
    (referenced1=m_Queue.take())=带有
    的“EOF”
    !(referenceID1=m_Queue.take()).equals(“EOF”)
    。与
    ==
    进行字符串比较不太可能奏效。@OldCurmudgeon您是对的。但正如尼古拉斯·菲洛托建议的那样,我完全删除了EOF部分。谢谢@好消息,是的,这种方法不再需要“EOF”