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
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”