我有一个多线程应用程序,该程序具有仅由主线程更新(写入)的集中列表。然后,我还有其他几个线程需要定期检索当前状态的列表。有没有一种方法可以让我做到这一点?
这取决于您要如何限制并发。最简单的方法可能是使用CopyOnWriteArrayList
。当您从中获取一个迭代器时,该迭代器将反映
该列表在创建迭代器时的外观 - 迭代器 将看不到后续修改。好处是它可以应付很多争用,缺点是添加新项相当昂贵。
另一种方法是锁定,最简单的方法可能是将列表包装在一起Collections.synchronizedList
并在迭代时在列表上进行同步。
第三种方法是使用某种形式BlockingQueue
并将新元素提供给工人。
编辑:
正如OP所述,仅需要快照,CopyOnWriteArrayList
这可能是最好的即用型替代方法。一种替代方法(用于廉价添加,但阅读成本较高)是仅synchronizedList
在需要遍历时创建副本(读取时复制而不是写入时复制):
List<Foo> originalList = Collections.synchronizedList(new ArrayList());
public void mainThread() {
while(true)
originalList.add(getSomething());
}
public void workerThread() {
while(true) {
List<Foo> copiedList;
synchronized (originalList) {
copiedList = originalList.add(something);
}
for (Foo f : copiedList) process(f);
}
}
编辑: 考虑一下,读取时复制的版本可以简化一些以避免所有synchronized
块:
List<Foo> originalList = Collections.synchronizedList(new ArrayList());
public void mainThread() {
while(true)
originalList.add(getSomething());
}
public void workerThread() {
while(true) {
for (Foo f : originalList.toArray(new Foo[0]))
process(f);
}
}
编辑2:
这是一个简单的包装,用于读取时复制列表,它不使用任何帮助程序,并且尝试尽可能细化锁定(我故意使它有些多余,以次优为准,以演示需要锁定的位置):
class CopyOnReadList<T> {
private final List<T> items = new ArrayList<T>();
public void add(T item) {
synchronized (items) {
// Add item while holding the lock.
items.add(item);
}
}
public List<T> makeSnapshot() {
List<T> copy = new ArrayList<T>();
synchronized (items) {
// Make a copy while holding the lock.
for (T t : items) copy.add(t);
}
return copy;
}
}
// Usage:
CopyOnReadList<String> stuff = new CopyOnReadList<String>();
stuff.add("hello");
for (String s : stuff.makeSnapshot())
System.out.println(s);
基本上,当您锁定时,您:
haproxy 的 ACL 用于实现基于请求报文的首部、响应报文的内容或其它的环境状态信息来做出转发决策,这大大增强了其配置弹性。其配置法则通常分为两步,首先去定义ACL,即定义一个测试条件,而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。定义ACL的语法格式如下。 acl <aclname> <criterion> [flags] [operator] <value> ..
问题内容: 我想用一个链表像中描述的这个文件。但是,我在网络上找不到任何Java实现。 如果上述链接列表的java实现不存在,我想我会使用。这是一个不错的选择(它实际上不是链接列表)吗? 如果不是一个好的选择,那么有人知道Java中可靠的并发(线程安全)无等待(无锁)链接列表实现吗? 问题答案: 是一个极好的无锁队列,它可以执行并发单个链表。一个小警告:如果您不使用poll或peek,而仅iter
问题内容: 如何创建并发的List实例,可以在其中按索引访问元素?JDK是否可以使用任何类或工厂方法? 问题答案: 中有一个并发列表实现。特别是。
问题内容: java中如何实现访问控制,public, protected, default和private关键字有何区别? 问题答案:
使用Camel拆分数组列表,并在多达10个线程中并行处理每个项目。以下是配置。线程池配置文件被设置为最大线程数=10。 bean:reportRepository?method=getPendingTransactions获取ArrayList并传递给Splitter。 是处理项目的处理器。 问题:当作业开始时,它正在启动10个线程,但是一些线程正在拾取同一个项目。例如,如果我在数组列表中有ite
在 Java 语言中提供了多个作用域修饰符,其中常用的有 public、private、protected、final、abstract、static、transient 和 volatile,这些修饰符有类修饰符、变量修饰符和方法修饰符。本文将详细介绍访问控制修饰符。 在实际生活中,如果要获取某件物品,与其直接穿过堡垒的墙壁,从而导致墙壁毁灭和破坏,不如通过门口的警卫请求进入堡垒的许可。一般而言