Multithreading 为什么使用消息队列而不是mulithreading?

Multithreading 为什么使用消息队列而不是mulithreading?,multithreading,message-queue,Multithreading,Message Queue,我有以下问题,我需要有人帮助我。我是消息队列的新手,最近开始查看Kestrel消息队列。 据我所知,线程和消息队列都用于应用程序中的并发,那么使用消息队列比多线程有什么优势呢 请帮忙 谢谢。事实上,一个促进了另一个。消息队列是一种很好且简单的多线程模式:当您通常有一个控制线程(但不一定是应用程序的主线程)和一个通常循环的工作线程池时,消息队列是促进对线程池控制的最简单方法 例如,要开始处理相对繁重的任务,您需要向队列中提交相应的消息。如果您有比当前处理的消息更多的消息,那么您的队列将增长,如果消

我有以下问题,我需要有人帮助我。我是消息队列的新手,最近开始查看Kestrel消息队列。 据我所知,线程和消息队列都用于应用程序中的并发,那么使用消息队列比多线程有什么优势呢

请帮忙
谢谢。

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

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


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

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

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


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

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

这允许您将生产者与消费者分离。您可以将要完成的工作分散到多个进程和机器上,并且可以彼此独立地管理/升级/移动这些程序

消息队列通常由一个或多个代理组成,这些代理负责分发消息,并确保消息不会丢失,以防发生不好的情况,例如程序崩溃、升级某个程序等


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

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

这允许您将生产者与消费者分离。您可以将要完成的工作分散到多个进程和机器上,并且可以彼此独立地管理/升级/移动这些程序

消息队列通常由一个或多个代理组成,这些代理负责分发消息,并确保消息不会丢失,以防发生不好的情况,例如程序崩溃、升级某个程序等


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

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

简而言之,信息传递对大脑来说更容易。详细地说

消息传递的工作原理是从一个代理向另一个代理发送内容。通常不需要协调对数据的访问。一旦代理接收到消息,它通常可以假定它对该数据具有无限制的访问权限


线程样式的工作原理是允许所有代理开放slather访问共享数据,但要求它们通过原语仔细协调访问。如果一个代理行为不端,进程就会被破坏,所有的地狱都会被打破。消息传递往往将问题局限于行为不端的代理及其队列,并且由于代理通常是自包含的,并且通常以顺序或状态机方式编程,它们往往不像传统的线程代码那样经常或神秘地出现错误行为。

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

简而言之,信息传递对大脑来说更容易。详细地说

消息传递的工作原理是从一个代理向另一个代理发送内容。通常不需要协调对数据的访问。一旦代理接收到消息,它通常可以假定它对该数据具有无限制的访问权限


线程样式的工作原理是允许所有代理开放slather访问共享数据,但要求它们通过原语仔细协调访问。如果一个代理行为不端,进程就会被破坏,所有的地狱都会被打破。消息传递往往将问题局限于行为不正常的代理及其队列,而且由于代理通常是自包含的,并且通常以顺序或状态机的方式编程,因此它们往往不会像传统线程代码那样频繁或神秘地出现行为不正常的情况。

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

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


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

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

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

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