为什么使用消息队列而不是多线程?

时间:2011-01-28 12:11:49

标签: multithreading message-queue

我有以下查询,我需要有人来帮助我。我是消息队列的新手,最近开始查看Kestrel消息队列。 据我所知,线程和消息队列都用于应用程序的并发性,那么使用消息队列而不是多线程有什么好处呢?

请帮忙 谢谢。

4 个答案:

答案 0 :(得分:4)

消息队列允许您在程序外进行通信。

这允许您将生产者与消费者分离。您可以将工作分散到多个流程和计算机上,并且可以相互独立地管理/升级/移动这些程序。

消息队列通常还包含一个或多个代理,负责分发您的消息并确保消息不会丢失,以防发生不良事件(例如,您的程序崩溃,升级其中一个程序等)。 / p>

消息队列也可能在程序内部使用,在这种情况下,它通常只是将数据从生产者线程交换/排队到消费者线程以进行异步处理的工具。

答案 1 :(得分:2)

实际上,一方便利另一方。消息队列是一个很好且简单的多线程模式:当你有一个控制线程(通常但不一定是应用程序的主线程)和一个(通常是循环的)工作线程池时,消息队列是促进控制线程的最简单方法池。

例如,要开始处理相对繁重的任务,请将相应的消息提交到队列中。如果您有比当前处理的消息更多的消息,那么您的队列会增长,如果更少,则反之亦然。当您的消息队列为空时,您的线程会休眠(通常保持锁定在互斥锁下)。

因此,没有什么可比较的:消息队列是多线程的一部分,因此它们被用于一些更复杂的多线程情况。

答案 2 :(得分:1)

对比消息队列和其他并发原语(如信号量,互斥量,条件变量等)更有意义。它们都可以在线程存在的情况下使用,尽管消息传递也常用于非线程上下文,例如进程间通信,而其他上下文往往局限于线程间通信和同步。

简短的回答是,大脑上的消息传递更容易。详细......

通过将内容从一个代理发送到另一个代理,消息传递起作用。通常不需要协调对数据的访问。一旦代理收到消息,它通常会认为它具有对该数据的无限制访问权。

“线程化”样式的工作原理是让所有代理人对共享数据进行开放式访问,但要求他们通过原语仔细协调其访问。如果一个代理人行为不端,那么这个过程就会被破坏,所有地狱都会崩溃。消息传递往往会将问题限制在行为不当的代理及其队列中,并且由于代理通常是自包含的并且通常以顺序或状态机方式编程,因此它们不会像传统的线程代码那样经常 - 或者神秘地 - 行为不端。

答案 3 :(得分:1)

创建线程很昂贵,并且每个同时“活动”的线程都会增加一定的开销,即使线程被阻塞等待某事发生。如果程序Foo有1000个要执行的任务并且并不真正关心它们完成的顺序,则可能创建1,000个线程并让每个线程执行一个任务,但这样的方法效率不会非常高。第二种选择是让一个线程按顺序执行所有1,000个任务。如果系统中有其他进程可以使用Foo没有使用的任何CPU时间,后一种方法将是高效的(并且可能是最佳的),但如果没有足够的工作来保持所有CPU忙,那么CPU会浪费一些时间闲着。在大多数情况下,让CPU闲置一秒钟与花费一秒钟的CPU时间一样昂贵(主要的例外是当一个人试图最小化电能消耗时,因为闲置的CPU可能比繁忙的CPU耗电少得多) )。

在大多数情况下,最好的策略是在这两种方法之间进行折衷:有一些线程(比如说10个)开始执行前十个任务。每次线程完成任务时,让它开始在另一个任务上工作,直到完成所有任务。使用这种方法,与线程相关的开销将减少99%,唯一的额外成本将是尚未启动的任务队列。由于队列条目容易比线程便宜得多(可能低于成本的1%,可能低于0.01%),这可以代表非常大的节省。

使用作业队列而不是线程的一个主要问题是,如果某些作业在列表中的作业运行之前无法完成,则系统可能会陷入死锁状态,因为后续任务直到较早才会运行任务已经完成。如果每个任务都被赋予一个单独的线程,那么这个问题就不会发生,因为与后面的任务相关联的线程最终会设法完成,从而让先前的任务继续进行。实际上,越早执行的任务被阻止,运行后者的CPU时间就越多。