我想实现生产者 - 消费者问题(一次只传输一个信息),但我希望制作人在离开前等待某人接收他的信息。
这是一个不阻止生产者的例子,但不是这样。
class Channel[T]
{
private var _msg : Option[T] = None
def put(msg : T) : Unit =
{
this.synchronized
{
waitFor(_msg == None)
_msg = Some(msg)
notifyAll
}
}
def get() : T =
{
this.synchronized
{
waitFor(_msg != None)
val ret = _msg.get
_msg = None
notifyAll
return ret
}
}
private def waitFor(b : => Boolean) =
while(!b) wait
}
如何更改它以便生产者被阻止(作为消费者)?
我试图在结束时添加另一个waitFor,但有时我的制作人不会被释放。
例如,如果我有put ; get || get ; put
,大部分时间都有效,但有时,第一个put
没有终止,左线程甚至从不运行get
方法(我会在put
调用终止后打印一些内容,在这种情况下,它永远不会打印出来。
答案 0 :(得分:2)
这就是为什么你应该在这种情况下使用标准类SynchronousQueue。
如果您真的想要处理有问题的代码,请首先向我们提供一个失败的测试用例或堆栈跟踪时的堆栈跟踪。
答案 1 :(得分:0)
您可以通过BlockingQueue后代执行此操作,其生成器put()方法创建一个信号量/事件对象,该对象使用传递的消息排队,然后生产者线程等待它。
使用者get()方法从队列中提取消息并发出信号,从而允许其原始生成器运行。
这允许同步队列'实际的排队功能,应该是你想要的吗?
答案 2 :(得分:0)
我想出了一些似乎有用的东西。
class Channel[T]
{
class Transfer[A]
{
protected var _msg : Option[A] = None
def msg_=(a : A) = _msg = Some(a)
def msg : A =
{
// Reading the message destroys it
val ret = _msg.get
_msg = None
return ret
}
def isEmpty = _msg == None
def notEmpty = !isEmpty
}
object Transfer {
def apply[A](msg : A) : Transfer[A] =
{
var t = new Transfer[A]()
t.msg = msg
return t
}
}
// Hacky but Transfer has to be invariant
object Idle extends Transfer[T]
protected var offer : Transfer[T] = Idle
protected var request : Transfer[T] = Idle
def put(msg : T) : Unit =
{
this.synchronized
{
// push an offer as soon as possible
waitFor(offer == Idle)
offer = Transfer(msg)
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be absorbed)
waitFor(offer isEmpty)
// delete the completed offer
offer = Idle
notifyAll
}
}
def get() : T =
{
this.synchronized
{
// push a request as soon as possible
waitFor(request == Idle)
request = new Transfer()
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be delivered)
waitFor(request notEmpty)
val ret = request.msg
// delete the completed request
request = Idle
notifyAll
return ret
}
}
protected def requestTransfer()
{
this.synchronized
{
if(offer != Idle && request != Idle)
{
request.msg = offer.msg
notifyAll
}
}
}
protected def waitFor(b : => Boolean) =
while(!b) wait
}
它具有尊重生产者和消费者之间对称性的优势,但它比我之前的要长一些。
感谢您的帮助。
编辑:它更好但仍然不安全......