【问题标题】:Which concurrent List for multiple writers one reader?多个作家一个读者的哪个并发列表?
【发布时间】:2017-05-24 06:57:11
【问题描述】:

我正在为多个线程实现日志记录,每个线程都会写入List。在所有线程完成后,我会将List 的内容转储到一个文件中。我应该使用哪个并发List 实现? 我正在考虑ConcurrentLinkedQueue

  • 写入将是并发的,但读取将在所有其他线程完成写入后由一个线程完成。

我可以为每个线程使用一个List,但是我会承担管理多个Lists 的开销,我不确定这是否值得。另一种选择是synchronized List

额外问题:如何让最后一个线程将列表转储到文件中?见Multiple threads arrive, the last should do the processing

【问题讨论】:

  • ArrayBlockingQueue ?
  • @StanislavL 需要我提前知道容量,我没有这个信息。
  • 请提供一个清晰、简洁的问题示例。我无法从您的问题中读取您要实现的目标以及遇到的代码问题。也许softwareengineering.stackexchange.com 是解决这个问题的更好地方。

标签: java multithreading concurrency java.util.concurrent


【解决方案1】:

请 - 不要

Java 已经内置了logging framework,它可以完全自定义以创建不同的处理程序和格式化程序。如果您出于某种原因不喜欢标准的 Java 日志框架,还有许多其他可用的。所有这些框架都处理并发。

随着您花在创建一个已经存在并完善了很长时间的框架上的时间,您本可以创建一些为世界增添新东西的东西。

【讨论】:

    【解决方案2】:

    如果您实际上可以保证“一旦所有其他线程都完成写入”就会发生任何读取队列的尝试,那么您根本不需要并发队列。

    您所需要的只是一个常规的、普通的、非并发队列,以及一个“日志条目使用者”工厂,它将日志条目使用者分配给需要写入队列的每个线程。

    消费者的使用隐藏了队列,所以线程唯一能做的就是追加到队列中。消费者的实现只是保证了对队列插入点的同步访问。

    然后队列不需要同步,因为如果它只是在“所有其他线程完成写入之后”被读取,那么显然,在读取它时不会发生并发访问。


    说了这么多:

    • 你确定“在所有其他线程都完成写入之后”部分吗?

    • 你如何定义“所有其他线程都已完成写入”?

    • 你怎么知道“所有其他线程都写完了”?

    • 为什么只在“所有其他线程都完成写入”之后才读取列表对您很重要?

    【讨论】:

    • 如此同步的列表就是答案。而且您仍然需要在编写器之后同步读取器以获得内存可见性效果。回答您的问题:所有写作线程都在CompletableFutures 中运行,我等到它们完成(“完成”)。完成它们很重要,因为之后List 的内容会被转储到文件中。
    • 多个线程写入同一个队列仍然需要一个并发队列。
    • @bowmore 不,它不会。我解释说,您所需要的只是消费者保证对队列插入点的同步访问。并发队列会在读取队列时引入额外的开销,这是不必要的,如果 OP 可以以某种方式保证读取只会在所有写入完成后发生。
    • 我看到您将作者称为“消费者”。通常这些被称为生产者。
    • @bowmore 不,他们是消费者。你有一些你想要记录的东西,你把它交给消费者,你不在乎它会发生什么。消费者的实现负责并发并将项目放入(否则不是并发的)队列中。
    猜你喜欢
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多