我是多线程的新手,我正在尝试编写以下简单程序:
我创建了以下类: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个线程无法满足我对“多线程”程序的需求。
我的猜测是我忘了发布一个资源,但我不知道为什么。
答案 0 :(得分:2)
您的问题是您在take()
中使用了Consumer
:
检索并删除此队列的头部,必要时等待 直到一个元素可用。
并且您测试返回的值是否为EOF
(不正确BTW,您需要使用equals)但是只将其放入队列中并且您有4 Consumer
所以3 {{1}还在等待它。
所以你应该使用Consumer
代替如下:
poll()
或者只是如果你摆脱while((referenceID1 = m_Queue.poll()) != null && !Objects.equals(referenceID1, "EOF"))
EOF