线程之间的Java同步列表。最佳实践

时间:2015-04-24 09:24:13

标签: java multithreading

当发生某些更改时,我正在创建数据库日志记录引擎。这些更改将被推送到一个线程中的队列,该线程每隔50ms处理队列中的25个LogObjects。

我在考虑使用Collections.synchronizedList()来保存我仍然需要在线程中处理的对象。

主应用程序线程通过ThreadObjInstance.LogList.add(new LogObject("Something to log");将LogObjects推送到列表中,并在我执行LogObject x = LogList.shift();的线程中处理它。

但是我觉得可能有更好的方法来做到这一点,或者这是一种完全可以接受的方法吗?或者我应该使用ArrayBlockingQueue来处理他的情况?或者另一个同步的列表对象......有很多选择。

这是我第一次使用线程,因此我试图弄清楚作业队列的最佳方法是什么,以及使用哪些对象来维护它。 我可以直接将内容添加到线程列表中吗?或者我是否需要在线程中使用同步方法?

问题基本上是:

  1. 我在哪里存储同步的对象列表以在两个线程之间处理(在处理线程或主线程中?)
  2. 从列表中添加/删除项目的最佳做法是什么?通过synchronized函数或直接在List对象上?
  3. 构建作业队列时,我对List对象的选择是什么?

3 个答案:

答案 0 :(得分:4)

  1. 您想要的任何地方,所有使用它的线程都可以访问它。
  2. BlockingQueue就是这样做的,您不需要自己进行任何同步。
  3. 无数,但BlockingQueue在这种情况下是最直接的(生产者 - 消费者)。

答案 1 :(得分:3)

您的选择主要围绕着由于某种原因备份队列以及您想要使用多少内存而想要发生的事情。

如果您习惯暂停主进程,直到日志记录线程清除了某些队列,那么ArrayBlockingQueue就可以了,因为它有界限(并且大小固定)并且在高负载下不会占用你的内存

如果你习惯于在备份日志记录时忽略内存问题(也许你确定日志记录线程将始终保持运行),那么LinkedBlockingQueue可能更适合,因为它稍微更优化并且无限制。它也可以给出一个大小限制,但这是可选的。

如果你使用其中任何一个,你不需要添加任何同步逻辑,因为它们自己完成。

  

在哪里存储同步的对象列表以在两个线程之间处理(在处理线程或主线程中?)

要么 - 您通常会在主线程中创建它并将其传递给您的日志记录线程和处理线程,因为它们都将共享它。

  

从列表中添加/删除项目的最佳做法是什么?通过synchronized函数或直接在List对象上?

BlockingQueue提供了一个丰富的线程安全添加和删除项目API。

  

构建作业队列时,我对List对象的选择是什么?

见上文。

答案 2 :(得分:1)

  1. 在这种情况下,似乎队列属于处理实体,即日志记录线程。但这仅仅是一个概念上的决定,在一天结束时,他们都必须持有对某种共享对象的引用。
  2. 最好公开一种添加项目的方法(你真的不想删除),而不是暴露整个列表,免费滥用。同样,这与同步没有任何关系,它只是封装的基本原则,或者如果你愿意的话,还是Demeter法则:只允许客户做尽可能少的事情。没有理由为什么主线程应该知道你如何实现队列(甚至有队列),除了"我可以把事件放在这里。"
  3. 队列可能最好由LinkedList表示,但由于队列可能很小而且操作不在关键路径上,因此选择可能不重要。使用最容易阅读和理解的内容。 (我和@Kayaman建议使用BlockingQueue,因为它需要你做很多工作,而且阅读代码的任何人都可以很容易地找出#&1&# 39;继续那里。)