我有一个图。该图由一个节点类组成,该节点类具有以下内容:
public abstract class AbstractNode{
public Collection<AbstractNode> predecessors;
public Collection<AbstractNode> successors;
//accept methods for visitors
}
我最近添加了一个组件,它允许您从YAML文件导入配置。该组件读取YAML文件,并使用该节点类生成一个图。这段代码相当慢,在图上进行了大量操作,包括遍历一些前置节点、分析各种节点,以及决定如何更新其他节点的后续节点和/或前置节点。
我们现有的代码有一个服务,它每100毫秒轮询一次相同的图形,以使用访问者在我们的程序中生成错误列表。访问者实际上是一类对象,它将通过每个继承者和前任列表为每个对象访问一次。
这会导致并发修改异常。:(
我的选择似乎是:
- 将轮询服务更新为事件驱动。
- 我们从事件驱动策略转向了轮询策略,因为事件的复杂性越来越高。这里面有很多微妙的时间问题
- 最适合模型的"纯度">
- 更新问题轮询服务和我的新yaml导入程序,使它们都在线程工作队列上同步(显而易见的选择是UI线程,因为它们已经有了基于队列的实现(
- 对UI框架的依赖性更强,如果UI框架不可用(并且我们的应用程序确实在无头命令行模式下运行(,那么怎么办
- 实现使用可关闭可迭代项的集合,这些可迭代项锁定其源,直到进行
close()
调用或hasNext()
返回false。这将允许我们要么阻止作者,直到读者完成。- 在可迭代项上搞砸。可能相当安全,因为实际上没有人再使用迭代器了,但这仍然是对契约的奇怪使用
- 更新AbstractNode以使用
CopyOnWriteArrayCollection
作为其前置器和后续器的备份集/列表- 用
List<String> predecessors = new CopyOnWriteArrayList<>()
替换机上友好POJOList<String> predecessors = new ArrayList<>()
代码 - 需要额外的序列化程序配置和/或生成讨厌的XML/JSON
- 用
- 通过将图突变操作推送到AbstractNode类上,将读取与写入模型分离,并替换getSuccessors/Precessors以返回防御副本和/或不可变集合(例如PCollections中的集合(
- 需要大量的代码来解决概念上非常小的问题
- 需要更新大量使用此图的位置(期望标准可变集合使用AbstractNode上的方法(
我真正想要的是一个集合框架,它是围绕组合而不是继承构建的。
将其转化为一秒钟的咆哮,并借助(大量(后见之明,它非常清楚地认识到,当面临创建抽象类及其多个实现的选择时,或者一个委托依赖项的类(读作:由其依赖项组成(时,后者是普遍可取的。
没有图书馆允许我做类似的事情吗
private final Collection<AbstractNode> predecessors = Collections.create(
DuplicationPolicies.ForbidDuplicates,
Orders.InsertionOrder,
Concurrency.ThrowOnConcurrentModification
);
对于LinkedHashSet<>
和
private final Collection<AbstractNode> predecessors = Collections.create(
DuplicationPolicies.AllowDuplicates,
Orders.InsertionOrder,
Concurrency.CopyOnWrite
);
对于CopyOnWriteArrayList<>
?
有了这样的系统,从一个厌恶并发的实现(如ArrayList(切换到一个容忍并发的实现,(如CopyOnWrite列表或Shared/Exclusive锁定列表(对我来说(可能(相当简单。
java中还没有现成的复合集合,但您可以使用标准java集合和一些作为类成员的附加对象轻松地手工实现它们。
由于您总是使用Orders.InsertionOrder
策略,所以类似列表的基本集合最适合您。您可以使用CopyOnWriteArrayList
作为实现Concurrency.CopyOnWrite
策略的基本集合,使用简单的ArrayList
来实现Concurrency.ThrowOnConcurrentModification
。
对于DuplicationPolicies
,用单个bool canAddElem(collection, elem)
方法附加对象就足够了。
类似的东西:
public class CompositeCollection extends Collection<AbstractNode>
{
private Collection<AbstractNode> baseCollection;
private filter;
public CompositCollection(DuplicationPolicies dPolicy, Concurrency cPolicy)
{
if(dPolicy == DuplicationPolicies.AllowDuplicates)
{
filter = new AllowDuplicatesFilter();
}
else
{
filter = new ForbidDuplicatesFilter();
}
if(cPolicy == Concurrency.Concurrency.CopyOnWrite)
{
baseCollection = new CopyOnWriteArrayList<AbstractNode>();
}
else
{
baseCollection = new ArrayList<AbstractNode>();
}
}
public bool add(AbstractNode node)
{
if(!filter->canAddElem(baseCollection, node)) {return false; }
return baseCollection->add(node);
}
...
};