【问题标题】:What should i use to solve this multithreading issue in java?我应该用什么来解决java中的这个多线程问题?
【发布时间】:2014-12-02 11:28:00
【问题描述】:

我对 Java 中的 Thread 非常陌生。在我的应用程序中,我将有一个线程(生产者),它将对输入数据进行一些处理,并不断将字符串对象添加到名为 A 的数据结构中(我知道要使用什么),同时,多个消费者线程取出什么在 A 中。每个消费者线程将一次取出一个对象,对其进行处理并放入另一个名为 B 的数据结构中。我已经阅读了有关线程和线程安全数据结构的信息,但我不知道哪种情况最适合我的情况。建议我不要使用 BlockingQueue 之类的阻塞数据结构,但没有很好地解释原因。有人可以向我解释为什么并向我推荐适合 A 和 B 的数据结构吗?

我正在考虑为 A 使用 LinkedList,为 B 使用 Treeset。我在正确的轨道上吗?

【问题讨论】:

  • 听起来 BlockingQueue 非常适合您的目的。我假设您正在为一堂课这样​​做,并且您的老师可能希望您构建自己的 BlockQueue ADT 版本。如果您对如何执行此操作感到困惑,您可能应该向您的老师寻求进一步的帮助
  • 在多线程从 A 中取出对象时,您介意向我解释一下 BlockingQueue 是如何工作的吗?哦,顺便说一句,这不是课堂作业,也不是为了构建我自己的 BlockQueue 版本。在我的实习工作中的一项职能中需要它。
  • 生产者可以放入对象,消费者可以从中提取对象的数据结构的通用名称是pool。队列、堆栈、堆、集合和多集合……都是不同种类的池,它们对可以进入池的内容有不同的规则,对事物出来的顺序有不同的规则。当它们不用于线程之间的通信时,相同的数据结构通常称为 containerscollections
  • 请查看我对我的实施草案的新更新...看起来还可以吗?

标签: java multithreading


【解决方案1】:

BlockingQueue 是实现生产者-消费者模式的首选工具。更多详细信息,请参阅Java Concurrency in Practice,第 5 章。

开始像LinkedListTreeSet 这样的非线程安全数据结构在这里肯定是错误的。我不知道您的同事为什么建议避免阻塞,但如果您尝试这样做,您几乎肯定会在此过程中重新发明阻塞数据结构,而且可能会很糟糕。

在您成为专家之前,坚持标准路径...

【讨论】:

  • 那么在多消费者阻塞队列的场景中,消费者是不是并行从A取东西呢?
  • 消费者可以“并行”从阻塞队列中获取。 (我会说“异步”;并行性略有不同。)当然,您必须正确设置消费者。每个都有自己的线程,没有其他锁会导致它们变成串行。
  • 嗨,我现在将尝试实现我的工作线程,并且真的很想向您展示以进行验证,但我不知道如何将您连接起来....我该怎么做?创建另一个 qns?
【解决方案2】:

LinkedList 不是线程安全的,你应该自己实现一些锁定逻辑。这同样适用于 TreeSet。因此,它们不是最好的方法。

BlockingQueue 听起来是个不错的选择,因为它提供了阻塞操作。例如。消费者可以阻止等待一个元素变得可用(被生产者添加到队列中)。此外,如果队列已满,生产者将被阻塞,直到消费者从队列中删除一个元素进行处理。

ConcurrentLinkedQueue 也是线程安全的。但它不提供我上面提到的阻塞操作(我想你会需要这些)。

我建议你去 BlockingQueue。

【讨论】:

  • 谢谢,正如你提到的,BlockingQueue 提供了阻塞操作……你能详细说明一下吗?所以它只会在A为空时阻塞,而当一个元素进来时它会自行解除阻塞?如果在许多线程等待取出东西的情况下,阻塞队列如何工作?
  • 是的,假设队列是空的。消费者线程调用 queue.take() 并被阻塞。只要一个元素被生产者线程添加到队列中,消费者线程就会被解除阻塞为了处理该项目。如文档 (docs.oracle.com/javase/7/docs/api/java/util/concurrent/…) 中所述,您可以拥有多个生产者/消费者线程。这个想法保持不变。其中一个消费者线程将拾取队列中的项目并对其进行处理(其余线程将保持阻塞状态)。另请检查:tutorials.jenkov.com/java-util-concurrent/blockingqueue.html
  • 非常gd教程链接非常感谢。顺便说一句,最后一个 qns,所以我是否必须执行 notify(),才能让因空而被阻塞的线程唤醒并开始占用?
  • 不,您不必担心“低级”同步调用,例如等待/通知[All]。您只需从队列中插入/删除元素,然后让 BlockingQueue 实现处理阻塞/解除阻塞线程。
  • 请查看我对我的实施草案的新更新...看起来还可以吗?
【解决方案3】:

根据我对你的问题的理解。

  1. 'A'(单实例)从某个地方获取数据,对数据进行一些处理,然后将该数据发布到某个“数据结构”中。
  2. B 的多个实例从该数据结构中读取并进行处理。

这是一种模式 --> 它被称为“管道和过滤器”模式,它最常用于对数据进行逐步处理的地方。一个过程的输出充当另一个过程的输入。在这种情况下 --> A , B 充当过滤器,数据结构是管道。在这种情况下,您需要使用队列数据结构: 1.队列应该是线程安全的 2.它应该是固定大小的,因为如果生产者比消费者快,你可能会耗尽所有内存并出现异常。 3. 如果队列已满,A 尝试往里面放数据,它不应该抛出异常,而是相应地在表单 A 中。

考虑到上述所有情况,您应该使用“LinkedBlockingQueue”

【讨论】:

  • 哇,所有的假设都完全是公牛眼。是的,我将使用多线程实现 LinkedBlockingQueue,几乎完成了……请留意我的下一篇文章,这样我就可以改进学习并给我的主管留下深刻印象。哈哈。非常感谢像你们这样的专家的见解和 cmet。
  • 请查看我对我的实施草案的新更新...看起来还可以吗?
猜你喜欢
  • 2021-01-14
  • 2011-03-29
  • 2019-08-02
  • 1970-01-01
  • 2015-09-30
  • 2015-06-13
  • 2021-04-09
  • 2022-11-30
  • 2021-08-18
相关资源
最近更新 更多