Java 冰棒不可变

标签 java concurrency immutability

我正在处理一个问题,我需要为一个问题加载大量输入,并处理这些输入以创建一个“问题空间”(即构建允许高效访问输入的数据结构等)。初始化完成后,多线程进程将启动,以并发方式广泛使用组织/处理的输入。

出于性能原因,我不想在并发阶段锁定和同步所有读取操作。我真正想要的是一个不可变的对象,多个读者可以同时安全访问。

出于实际原因(可读性和可维护性),我不想使 InputManager 成为真正的不可变对象(immutable对象)(即所有字段“最终”并在构造中初始化)。 InputManager 将有许多数据结构(列表和映射),其中每个对象都有许多相互循环引用。这些对象被构造为“真正的”不可变对象(immutable对象)。我不希望 InputManager 有 14 个参数的构造函数,但我确实需要 InputManager 类在构建后提供一致的、只读的问题空间 View 。

我想要的是 Eric Lippert 讨论的“冰棒不变性”here.

我采用的方法依赖于使用所有变异方法的“包可见性”,并在单个包中执行所有可变操作(即 InputManager 的构造)。 setter/getter 都具有公共(public)可见性。

类似于:

public final class InputManager {  // final to prevent making mutable subclasses 
    InputManager() { ... } //package visibility limits who can create one
        HashMap<String,InputA> lookupTable1;
        ...

    mutatingMethodA(InputA[] inputA) { //default (package visibility)
        //setting up data structures...
    }

    mutatingMethodB(InputB[] inputB) { //default (package visibility)
        //setting up data structures...
    }

    public InputA getSpecificInput(String param1) {
        ... //access data structures
        return objA; //return immutable object
    }
}

总体思路(如果我还不够清楚的话)是我将在单个线程中构建 InputManager,然后将其传递给多个线程,这些线程将使用该对象执行并发工作。我想尽可能地强制执行这个“两阶段”可变/不可变对象(immutable对象)生命周期,而不做一些太“可爱”的事情。寻找关于实现此目标的更好方法的评论或反馈,因为我确信这不是一个罕见的用例,但我也找不到支持它的设计模式。

谢谢。

最佳答案

就我个人而言,我会坚持使用您简单而充分的方法,但如果您有兴趣,可以使用可变伴侣 习语。您编写了一个具有修改器的内部类,同时重用了封闭实例中的所有字段和 getter。

一旦您失去可变伴侣,它留下的封闭实例就会真正不可变。

关于Java 冰棒不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13055266/

相关文章:

c# - 在 C# 中,为什么我不能在 foreach 循环中修改值类型实例的成员?

javascript - 是否可以使 HTML 元素属性不可变?

java - Android recyclerview 滚动到顶部

java - 斯卡拉。 float 的奇怪结果

java - 如何在Java中正确使用keyListener

java - 有没有办法在 GAE GWT 应用程序中登录文件?

concurrency - 如何在Eclipse CDT中使用GCC/G++编译并运行C++0x?

go - 我们如何确定 "last"工作进程/线程在 Go 中何时完成?

java - Java 中的同步多线程(Apache HTTPClient)

java - 将对象缓存为不可变类