我有两个主题,一个消费者和一个制作人。消费者线程是主线程,而生产者线程是由我使用的第三方库创建的。
您使用List
的{{1}}向生产者线程请求ProducerChannel
数据,该requestData()
会立即返回。然后,生产者线程将异步生成数据,并使用回调方法发送每个数据。我想要请求数据的方法同步返回结果。最直接的方法是使用wait()
和notify()
,如下所示。
public class DataFeed {
boolean done;
private List<Data> dataList;
private ProducerChannel producerChannel;
// This method should be synchronous.
public List<Data> getDataList() {
this.producerChannel.requestData();
while (!done) {
wait();
}
List<Data> dataList = this.dataList;
this.dataList = null;
return dataList;
}
// This is the call back method invoked by the producer thread.
public void generated(Data data) {
if (data == null) {
done = true; // End of data.
notify();
}
else {
this.dataList.add(data);
}
}
}
请注意,整个应用程序中只有一个消费者线程。这就是DataFeed
只有一个List
来保存每个请求的结果的原因。我了解到Executor框架现在是管理线程的首选方式。如何重构此类,以便在不创建其他线程时不显式使用Thread
个对象?
答案 0 :(得分:2)
我认为你应该看一下BlockingQueue javadoc上的生产者 - 消费者例子:
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html
答案 1 :(得分:1)
我真的不关注你。此类不会创建任何线程。因此,使用执行程序框架不会让你在这里。
使用wait和notify,使用显式同步和线程通信,您可以使用BlockingQueue。生产者在数据准备好时将列表添加到阻塞队列,并且在阻塞队列为空时消耗器阻塞。
答案 2 :(得分:1)
如果您不关心生成的集合的大小或按索引获取项目,那么BlockingQueue可能就是您所需要的。如果你关心那些事情(即你实际上需要一个java.util.List
而不是Collection
,或者如果由于某种原因你不能使用延迟集合那么你仍然可以使用{{1 }和wait()
。
您需要将他们的synchronized关键字添加到您的getDataList和生成的方法中,否则您将获得notify()
。
像这样:IllegalStateMonitorException
但如果这是您想要去的路线,请谨慎使用。任意数量的线程都可以同时调用public synchronized List<Data> getDataList() throws InterruptedException{
。即使它已同步,您也可以通过调用getDataList()
就个人而言,我会选择BlockingQueue
答案 3 :(得分:0)
Here is the example关于如何使用阻止队列来解决生产者消费者问题
答案 4 :(得分:0)
我是OP。虽然BlockingQueue肯定会奏效,但我了解到Semaphore将是一个更简单的解决方案。