我使用下面的代码来实现和测试阻塞队列。我通过启动 5 个并发线程(移除器)从队列中拉出项目来测试队列,如果队列为空则阻塞,并启动 1 个并发线程(加法器)间歇性地将项目添加到队列中。但是,如果我让它运行足够长的时间,我会得到一个异常,因为即使队列为空,移除线程之一也会退出等待状态。
有谁知道为什么我得到异常?请注意,我很想知道为什么这与有效的解决方案不同(因为我可以谷歌搜索)。
非常感谢您的帮助。
using System;
using System.Threading;
using System.Collections.Generic;
namespace Code
{
class Queue<T>
{
private List<T> q = new List<T>();
public void Add(T item)
{
lock (q)
{
q.Add(item);
if (q.Count == 1)
{
Monitor.Pulse(q);
}
}
}
public T Remove()
{
lock (q)
{
if (q.Count == 0)
{
Monitor.Wait(q);
}
T item = q[q.Count - 1];
q.RemoveAt(q.Count - 1);
return item;
}
}
}
class Program
{
static Random r = new Random();
static Queue<int> q = new Queue<int>();
static int count = 1;
static void Adder()
{
while (true)
{
Thread.Sleep(1000 * ((r.Next() % 5) + 1));
Console.WriteLine("Will try to add");
q.Add(count++);
}
}
static void Remover()
{
while (true)
{
Thread.Sleep(1000 * ((r.Next() % 5) + 1));
Console.WriteLine("Will try to remove");
int item = q.Remove();
Console.WriteLine("Removed " + item);
}
}
static void Main(string[] args)
{
Console.WriteLine("Test");
for (int i = 0; i < 5; i++)
{
Thread remover = new Thread(Remover);
remover.Start();
}
Thread adder = new Thread(Adder);
adder.Start();
}
}
}
最佳答案
if I leave it running for long enough I get an exception because one of the remover threads comes out of a waiting state even when the queue is empty. Does anyone know why I get the exception?
这个问题很奇怪,因为您显然知道答案:您的第一句话回答了第二句话提出的问题。 您得到异常是因为当队列为空时移除线程退出等待状态。
要解决此问题,您需要使用循环而不是“if”。正确的代码是:
while(q.Count == 0) Monitor.Wait(q);
不是
if(q.Count == 0) Monitor.Wait(q);
有评论者指出,您的问题可能是“队列为空时,消费者线程在什么情况下可以获得监视器?”
嗯,您比我们更有能力回答这个问题,因为您是运行程序并查看输出的人。但就在我的脑海中,这是一种可能发生的方式:
现在线程 1 在监视器中,队列为空。
一般来说,在推理这类问题时,您应该将“Pulse”想象成一只附有便条的鸽子。一旦被释放,它就与发件人没有联系,如果找不到它的家,它就会死在荒野中,而它的信息也没有送达。当你使用 Pulse 时,你所知道的是,如果有任何线程在等待,那么一个线程将在未来的某个时间进入就绪状态;您对线程操作的相对时间一无所知。
关于c# - 在 C# 中实现阻塞队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9422133/
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
我需要在RubyonRails中实现无向图G=(V,E)并考虑构建一个Vertex和一个Edge模型,其中Vertex有_多条边。由于边恰好连接两个顶点,您将如何在Rails中执行此操作?您是否知道任何有助于实现此类图表的gem或库(对重新发明轮子不感兴趣;-))? 最佳答案 不知道有任何现有库在ActiveRecord之上提供图形逻辑。您可能必须实现自己的Vertex、EdgeActiveRecord支持的模型(请参阅Rails安装的rails/activerecord中的vertex.rb和edge.rb/test/fixtur
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我haveaclass它公开了一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过to_s和to_i公开它们之外,我还使用to_str和to_int,如下所示:classStatusdefto_s@outputendalias:to_str:to_sdefto_i@status.exitstatusendalias:to_int:to_iend我的想法是能够在尽可能多的情况下使用这个对象。将其强制转换为字符串或整数会增加可用性。例如,我可以将对象与字符串连接起来:a_string="Outputwas:"+results(我想用这个作为int强制转换的例子,但是Fixnum
我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几
我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true: