5

如果队列已满,ArrayBlockingQueue 将阻塞生产者线程,如果队列为空,它将阻塞消费者线程。

这种阻塞的概念不是与多线程的想法背道而驰吗?如果我有一个“主”线程,让我们说我想将所有“记录”活动委托给另一个线程。所以基本上在我的主线程中,我创建了一个 Runnable 来记录输出,并将 Runnable 放在一个 ArrayBlockingQueue 上。这样做的全部目的是让“主”线程立即返回,而不会在昂贵的日志记录操作中浪费任何时间。

但是如果队列已满,主线程将被阻塞并等待直到有可用的位置。那么它对我们有什么帮助呢?

4

8 回答 8

9

队列不会出于恶意而阻塞,它会阻塞以将额外的质量引入系统。在这种情况下,它是防止饥饿

想象一组线程,其中一个线程非常快地生成工作单元。如果允许队列无限增长,那么“快速生产者”队列可能会占用所有生产能力。有时,防止这种副作用比让所有线程畅通更重要。

于 2013-07-05T18:33:38.217 回答
5

我想这是设计师的决定。如果他选择阻塞模式 ArrayBlockingQueue 提供了put方法。如果设计者不想要阻塞模式 ArrayBlockingQueue 有offer方法,当队列已满时将返回 false ,但他需要决定如何处理 reected 日志事件。

于 2013-07-05T18:33:17.410 回答
3

在您的示例中,我认为阻塞是一项功能:它可以防止 OutOfMemoryError。

一般来说,您的一个线程不够快,无法应付分配的负载。所以其他人必须以某种方式放慢速度,以免危及整个应用程序。

另一方面,如果负载均衡,队列不会阻塞。

于 2013-07-05T18:34:59.347 回答
2

阻塞是多线程的必要功能。您必须阻止才能同步访问数据。它不会违背多线程的目的。

我建议在生产者尝试将项目提交到已满的队列时抛出异常。我相信有一些方法可以预先测试容量是否已满。

这将允许调用代码决定它想如何处理一个完整的队列。

如果处理队列中的项目时的执行顺序不重要,我建议使用线程池(在 Java 中称为 ExecutorService)。

于 2013-07-05T18:31:13.813 回答
1

这取决于您的多线程哲学的性质。对于我们这些喜欢通信顺序进程的人来说,阻塞队列几乎是完美的。事实上,理想的情况是,除非接收者准备好接收,否则根本无法将消息放入队列。

所以不,我不认为阻塞队列违背了多线程的目的。实际上,您描述的场景(主线程最终停止运行)很好地说明了多线程参与者模型的主要问题;你不知道它是否会死锁/阻塞,你也不能详尽地测试它。

相反,想象一个零消息深度的阻塞队列。这样系统才能正常工作,您必须找到一种方法来确保始终保证记录器能够从主线程接收消息。这就是 CSP。这可能意味着在您假设的记录器线程中,您必须具有应用程序定义的缓冲(与某些框架开发人员对 FIFO 应该有多深的最佳猜测相反)、快速 I/O 子系统、检查是否跟上、处理方式落后等等。简而言之,它不会让你侥幸逃脱,你不得不解决系统性能的各个方面。

这当然更难,但这样你最终会得到一个绝对没问题的系统,而不是如果你的阻塞队列是未知数量的消息深度时你所拥有的可疑的“可能”。

于 2013-07-05T19:04:12.807 回答
0

听起来您对为什么要ArrayBlockingQueue在线程之间使用诸如 an 之类的东西有一个大致的了解。

拥有一个阻塞队列让你可以选择做一些不同的事情,以防你的后台工作线程出现问题,而不是盲目地向队列添加更多请求。如果队列中有空间,则没有阻塞。

但是,对于您的特定用例,我将使用ExecutorService而不是直接读取/写入队列,这会创建一个后台工作线程池:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

pool = Executors.newFixedThreadPool(poolSize);
pool.submit(myRunnable);
于 2013-07-05T18:31:05.083 回答
0

当队列已满时,您必须选择要做什么。在 Array Blocking队列的情况下,选择是等待。

如果队列已满,另一种选择是丢弃新对象;你可以通过offer来实现。

你必须做出取舍。

于 2013-07-05T18:31:15.807 回答
0

多线程程序是不确定的,因为你不能事先说:n 个生产者动作将与 m 个消费者动作一样长。因此,在每种情况下,n 个生产者和 m 个消费者之间的同步都是必要的。

您需要选择队列大小,以便在大多数情况下使活动的生产者和消费者的数量最大化。但是java的线程模型并不能保证任何消费者都会运行,除非它是唯一未被阻塞的线程。(当然,在多核 CPU 上,消费者很可能会运行)。

于 2013-07-05T18:39:29.187 回答