Java Popsicle Immutable

I am working on a problem when I need to load a large amount of input into a problem, and process these inputs to create a "problem space" (that is, create data structures that provide efficient access to inputs, etc.). Upon completion of this initialization, a multi-threaded process begins, which actively uses organized / processed input data in parallel.

For performance reasons, I do not want to block and synchronize all read operations in the parallel phase. What I really want is an immutable object, safe for multiple readers to access simultaneously.

For practical reasons (readability and maintainability), I do not want the InputManager to be a true immutable object (that is, all fields are “final” and initialized in the design). The InputManager will have many data structures (lists and maps), where each object has many circular links to each other. These objects are constructed as "true" immutable objects. I don't want to have a 14 argument constructor for the InputManager, but I need the InputManager class to provide a consistent read-only view of the problem space after it is built.

What I am going to do is the “Eskimo immutability,” as discussed by Eric Lippert here.

The approach that I take is based on using the "package visibility" of all mutation methods and performing all mutable actions (i.e., building the InputManager) in one package. Getters all have public visibility.

Sort of:

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 } } 

The general idea, if I was not clear enough, is that I will create an InputManager in one thread, and then pass it to several threads that will do parallel work using the object. I want to ensure that this “two-phase” mutable / immutable life cycle of an object is fulfilled, and also possibly without doing anything too “sweet”. Looking for comments or feedback on the best ways to achieve this, as I'm sure this is not an unusual use case, but I cannot find a design template that supports it.

Thanks.

+4
source share
3 answers

Personally, I will stay with your simple and sufficient approach, but in case you are interested, there is such a thing as a volatile idiom of a companion. You write an inner class that has mutators when reusing all the fields and getters from the closing instance.

Once you lose the volatile companion, the closing instance that it leaves is really unchanged.

+1
source

I think you can just have separate interfaces for your two phases. One for part of the building, another for reading. This way you clearly share your access patterns. You can see this as an instance of the segregation separation principle (pdf) :

Clients should not depend on interfaces that they do not use.

+1
source

While the object is being published safely, and readers cannot mutate it.

“Publishing” here means how the creator makes the object available to readers. For example, the creator places it in the lock queue, and readers poll the queue.

It depends on your publishing method. I bet it's safe.

+1
source

Source: https://habr.com/ru/post/1441878/


All Articles