Usefulness of immutable objects when the state of a program constantly changes - java

I know that immutable objects always have the same state, the state in which they are actually created. Their invariants are establised by the constructor and since their state does not change after construction , those invariants always hold good and this is why they are safe to publish in a multi threaded environment. This is all fine but since we live in a dynamic world , where the state of program changes continuously , what benefits do such objects give us if we construct the state of our program through immutable objects?

"what benefits do such objects give us" you already answered that.
Regarding the "dynamic" part of your question, if you need to "change" an immutable object, you can create a new one from the old one:
Immutable oldObj = new Immutable(...);
Immutable newObj = new Immutable(oldObj.property1, "a new value for property 2");
If you find that you keep doing that repeatedly, then maybe you need to make the object mutable and add the relevant tread-safety features that are needed to be able to use that object in a concurrent environment.

Immutable objects allow you to cleanly communicate changes of state to different threads.
It is a good practice to use immutable objects to represent messages exchanged between threads. Once such message is sent, its payload can not be altered, which prevents many concurrency related bugs. If a thread needs to communicate some further changes, it just sends next messages.

Immutable objects are very helpful when you need some static object whose state never changes .Greatest advantage are immutability , object semantics and smart pointers renders object ownership a moot point. Implicitly this also means deterministic behaviour in the presence of concurrency.
Java has already defined some Immutable classes like String Integer.
Other benefit is they always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state .
Let say if you have a global cache of static objects like country codes , here you can apply Immutability.
Why do we need immutable class?

Immutable objects are really useful in cases like this, with a String object:
public class A {
private volatile String currentName = "The First Name";
public String getCurrentName() {
// Fast: no synching or blocking! Can be called billions of times by
// billions of threads with no trouble.
// (Does need to be read from memory always because it's volatile.)
return currentName;
}
public whatever someMethod() {
... code ...
// Simple assignment in this case. Could involve synchronization
// and lots of calculations, but it's called a lot less than
// getCurrentName().
currentName = newName;
... code ...
}
}
public class B {
... in some method ...
A objA = something;
// Gets "name" fast despite a billion other threads doing the same thing.
String name = objA.getCurrentName();
// From this point on, String referenced by "name" won't change
// regardless of how many times A.currentName changes.
... code with frequent references to objA
}
This allows complex data (or even simple data, this case) that must be consistent (if not precisely up-to-date) to be updated and delivered to anybody who wants it very quickly and in a thread-safe manner. The data delivered will soon become outdated, perhaps, but it will keep its value during the calling method and remain consistent.

Related

Best practices or principles for sharing objects between threads in Java

I tried to search but couldn't find exact answer I was looking for hence putting up a new question.
If you wish to share any mutable object(s) between multiple threads, are there any best practices/principles/guidelines to do it ?
Or will it simply vary case by case ?
Sharing mutable objects between threads is risky.
The safest way is to make the objects immutable, you can then share them freely.
If they must be mutable then each of the objects each needs to ensure their own thread safety using the usual methods to do so. (synchronized, AtomicX classes, etc).
The ways to protect the individual objects will vary a lot though depending on how you are using them and what you are using them for.
In java, you should synchronize any method that changes/reads the state of shared object, it is the easiest way.
other strategies are:
make use of thread safe classes (ConcurrentHashMap) for example
use of locks
use of volatile keyword, to avoid stale objects (sometimes could be used as lightweight synchronizer)
they key is sync your updates/reads to guarantee consistent state, the way you do it, could vary a lot.
The problems with sharing objects between threads are caused by having the two threads access the same data structure at the same time, with one mutating the structure while the other depends on the structure to be complete, correct or stable. Which of these cause the problem is important and should be considered when choosing the strategy.
These are the strategies I use.
Use immutable objects as much as possible.
This removes the issue of changing the data structure altogether. There are however a lot of useful patterns that can not be written using this approach. Also unless you are using a language/api which promotes immutability it can be inefficient. Adding a entry to a Scala list is much faster than making a copy of a Java list and adding a entry to the copy.
Use the synchronize keyword.
This ensures that only one thread at a time is allowed to change the object. It is important to choose which object to synchronize on. Changing a part of a structure might put the hole structure in an illegal state until another change is made. Also synchronize removes many of the benefits of going multithreaded in the first place.
The Actor model.
The actor model organizes the world in actors sending immutable messages to each other. Each actor only has one thread at once. The actor can contain the mutability.
There are platforms, like Akka, which provide the fundamentals for this approach.
Use the atomic classes. (java.util.concurrent.atomic)
These gems have methods like incrementAndGet. They can be used
to achieve many of the effects of synchronized without the overhead.
Use concurrent data structures.
The Java api contains concurrent data structures created for this purpose.
Risk doing stuff twice.
When designing a cache it is often a good idea to risk doing the work twice instead of using synchronize. Say you have a cache of compiled expressions from a dsl. If an expression is compiled twice that is ok as long as it eventually ends up in the cache. By allowing doing some extra work during initialization you may not need to use the synchronize keyword during cache access.
There is example. StringBuilder is not thread safe, so without synchronized (builder) blocks - result will be broken. Try and see.
Some objects are thread safe (for example StringBuffer), so no need to use synchronized blocks with them.
public static void main(String[] args) throws InterruptedException {
StringBuilder builder = new StringBuilder("");
Thread one = new Thread() {
public void run() {
for (int i = 0; i < 1000; i++) {
//synchronized (builder) {
builder.append("thread one\n");
//}
}
}
};
Thread two = new Thread() {
public void run() {
for (int i = 0; i < 1000; i++) {
//synchronized (builder) {
builder.append("thread two\n");
//}
}
}
};
one.start();
two.start();
one.join();
two.join();
System.out.println(builder);
}
Although there are some good answers already posted, but here is what I found while reading Java Concurrency in Practice Chapter 3 - Sharing Objects.
Quote from the book.
The publication requirements for an object depend on its mutability:
Mutable objects can be published through any mechanism;
Effectively immutable objects (whose state will not be modified after publication) must be safely published;
Mutable objects must be safely published, and must be either threadsafe or guarded by a lock.
Book states ways to safely publish mutable objects:
To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:
Initializing an object reference from a static initializer;
Storing a reference to it into a volatile field or AtomicReference;
Storing a reference to it into a final field of a properly constructed object; or
Storing a reference to it into a field that is properly guarded by a lock.
The last point refers to using various mechanisms like using concurrent data structures and/or using synchronize keyword.

Is it safe in Java to read (not modify) objects which are not thread safe (like linked list) from multiple threads?

there was already a question whether threads can simultaneously safely read/iterate LinkeList. It seems the answer is yes as far as no-one structurally changes it (add/delete) from the linked list.
Although one answer was warning about "unflushed cache" and advicing to know "java memory model". So I'm asking to elaborate those "evil" caches. I'm a newbie and so far I still naively believe that following code is ok (at least from my tests)
public static class workerThread implements Runnable {
LinkedList<Integer> ll_only_for_read;
PrintWriter writer;
public workerThread(LinkedList<Integer> ll,int id2) throws Exception {
ll_only_for_read = ll;
writer = new PrintWriter("file."+id2, "UTF-8");
}
#Override
public void run() {
for(Integer i : ll_only_for_read) writer.println(" ll:"+i);
writer.close();
}
}
public static void main(String args[]) throws Exception{
LinkedList<Integer> ll = new LinkedList<Integer>();
for(int i=0;i<1e3;i++) ll.add(i);
// do I need to call something special here? (in order to say:
// "hey LinkeList flush all your data from local cache
// you will be now a good boy and share those data among
// whole lot of interesting threads. Don't worry though they will only read
// you, no thread would dare to change you"
new Thread(new workerThread(ll,1)).start();
new Thread(new workerThread(ll,2)).start();
}
Yes, in your specific example code it's okay, since the act of creating the new thread should define a happens-before relationship between populating the list and reading it from another thread." There are plenty of ways that a seemingly-similar set up could be unsafe, however.
I highly recommend reading "Java Concurrency in Practice" by Brian Goetz et al for more details.
If your code created and populated the list with a single thread and only in a second moment you create other threads that concurrently access the list there is no problem.
Only when a thread can modify a value while other threads try to read the same value can happens problems.
It can be a problem if you change the object you retrieve (also if you don't change the list itself).
Although one answer was warning about "unflushed cache" and advicing to know "java memory model".
I think you are referring to my Answer to this Question: Can Java LinkedList be read in multiple-threads safely?.
So I'm asking to elaborate those "evil" caches.
They are not evil. They are just a fact of life ... and they affect the correctness (thread-safety) reasoning for multi-threaded applications.
The Java Memory Model is Java's answer to this fact of life. The memory model specifies with mathematical precision a bunch of rules that need to be obeyed to ensure that all possible executions of your application are "well-formed". (In simple terms: that your application is thread-safe.)
The Java Memory Model is ... difficult.
Someone recommended "Java Concurrency in Practice" by Brian Goetz et al. I concur. It is the best textbook on the topic of writing "classic" Java multi-threaded applications, and it has a good explanation of the Java Memory Model.
More importantly, Goetz et al gives you a simpler set of rules that are sufficient to give you thread-safety. These rules are still too detailed to condense into StackOverflow answer ... but
one of the concepts is "safe publication", and
one of the principles is to use / re-use existing concurrency constructs rather than to roll your own concurrency mechanisms based on the Memory Model.
I'm a newbie and so far I still naively believe that following code is ok.
It >>is<< correct. However ...
(at least from my tests)
... testing is NOT a guarantee of anything. The problem with non-thread-safe programs is that the faults are frequently not revealed by testing because they manifest randomly, with low probability, and often differently on different platforms.
You cannot rely on testing to tell you that your code is thread-safe. You need to reason1 about the behaviour ... or follow a set of well-founded rules.
1 - And I mean real, well-founded reasoning ... not seat-of-the-pants intuitive stuff.
The way you're using it is fine, but only by coincidence.
Programs are rarely that trivial:
If the List contains references to other (mutable) data, then you'll get race conditions.
If someone modifies your 'reader' threads later in the code's lifecycle, then you'll get races.
Immutable data (and data structures) are by definition thread-safe. However, this is a mutable List, even though you're making the agreement with yourself that you won't modify it.
I'd recommend wrapping the List<> instance like this so the code fails immediately if someone tries to use any mutators on the List:
List<Integer> immutableList = Collections.unmodifiableList(ll);
//...pass 'immutableList' to threads.
Link to unmodifiableList
You need to guarantee happens-before relationship between reads and writes in your LinkedList because they are done in separate threads.
Result of ll.add(i) will be visible for new workerThread because Thread.start forms happens-before relationship. So your example is thread safe. See more about happens-before conditions.
However be aware of more complex situation, when LinkedList is read during iteration in worker threads and at the same time it is modified by the main thread. Like this:
for(int i=0;i<1e3;i++) {
ll.add(i);
new Thread(new workerThread(ll,1)).start();
new Thread(new workerThread(ll,2)).start();
}
This way ConcurrentModificationException is possible.
There are several options:
Clone your LinkedList inside of workerThread and iterate the copy
instead.
Use synchronization both for list modification and for list
iteration (but it will lead to poor concurrency).
Instead of LinkedList use CopyOnWriteArrayList.
Sorry for answering to my question. But I was thinking of your reassuring answers and I found it may not be so safe as it seems. I found and tested case when it is not working - if object would use it's class variable for storing any data (I wouldn't know about) then it would fail (then the only question is if linked list (and other java classes) in some implementation can do it...) See failing example:
public class DummyLinkedList {
public LinkedList<Integer> ll;
public DummyLinkedList(){
ll = new LinkedList<Integer>();
}
int lastGetIndex;
int myDummyGet(int idx){
lastGetIndex = idx;
//return ll.get(idx); // thids would work fine as parameter is on the stack so uniq for each call (at least if java supports reentrant functions)
return ll.get(lastGetIndex); // this would make a problem even for only readin the object - question is how many such issues java.* contains
}
}
It depends on how the object was created and made available to your thread. In general, no, it's not safe, even if the object isn't modified.
Following are some ways to make it safe.
First, create the object and perform any modification that is necessary; you can consider the object to be effectively immutable if no more modifications occur. Then, share the effectively immutable object with other threads by one of the following means:
Have other threads read the object from a field that is volatile.
Write a reference to the object inside a synchronized block, then have other threads read that reference while synchronized on the same lock.
Start the reading threads after the object is initialized, passing the object as a parameter. (This is what you are doing in your example, so you are safe.)
Pass the object between threads using a concurrent mechanism like a BlockingQueue implementation, or publish it in a concurrent collection, like a ConcurrentMap implementation.
There might be others. Alternatively, you can make all of the fields of the shared object final (including all the fields of its Object members, and so on). Then it will be safe to share this object by any means across threads. That's one of the under-appreciated virtues of immutable types.
If you only access to the list is by 'read' methods (including iterations) then you are fine. Like in your code.

Java Immutable Objects [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am learning the concept of immutability.
I understand that immutable objects cannot change their values once the object is created.
But I didn't understand the following uses of immutable objects.
They are
are automatically thread-safe and have no synchronization issues. How ? Proof ?
do not need a copy constructor. How ? Any example ?
do not need an implementation of clone How ? Any example ?
do not need to be copied defensively when used as a field How ? Any example ?
always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state. How ? Any example ?
Could someone please explain each of these points in detail with examples supporting it ?
Thanks.
..are automatically thread-safe and have no synchronization issues
Concurrency problems happen when two different threads modify the state of the same object. Immutable objects can't be modified, so no problems.
Example: A String. Two threads can be passed the same String without worry since neither can mutate it in any way.
do not need a copy constructor
... because copy is the only way to mutate it. One common design pattern for immutable objects for every "modification" operation to make a copy and then perform the operation on the new object.
Copy constructors are usually used on objects that you want to change without affecting the original. This is always the case (by definition) with immutable objects.
In the case of String, all the methods and the + operator return new Strings.
do not need an implementation of clone
see above.
do not need to be copied defensively when used as a field
Once upon a time I did something silly. I had a set of enums in a List:
private static final List<Status> validStatuses;
static {
validStatuses = new ArrayList<Status>();
validStates.add(Status.OPEN);
validStates.add(Status.REOPENED);
validStates.add(Status.CLOSED);
}
This list was returned from a method:
public static List<Status> getAllStatuses() {
return validStates;
}
I retrieved that list but only wanted to show the open states in the interface:
List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED);
Great, it worked! Wait, now all status lists are showing only those two -- even after page refresh! What happened? I modified a static object. Oops.
I could have used defensive copying on the return object of getAllStatuses. Or, I could use something like Guava's ImmutableList in the first place:
private static final List<Status> validStatuses =
ImmutableList.of(Status.OPEN, Status.REOPENED, Status.CLOSED);
Then when I did something dumb:
List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED); // Exception!
always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state.
Because the class can never be modified, all states emitted by modification are whole, qualified objects (because they cannot change, they must always be in a qualified state to be useful). An exception would not emit a new object and therefore you can never have an undesirable or indeterminate state.
They are automatically thread-safe and have no synchronization issues
Yes due to the guarantees provided by the Java Memory Model for final fields:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads.
do not need to be copied defensively when used as a field How ? Any example ?
Because they are immutable, they can't be modified, so it is fine to share them with external code (you know they won't be able to mess up with the state of the object).
Corollary: you don't need to copy / clone immutable objects.
always have "failure atomicity"
An immutable object does not change once it is properly constructed. So either construction fails and you get an exception or it does not and you know the object is in a consistent state.
It's not a concept that can be usefully explained with examples of it. The advantage of immutable objects is that you know their data cannot change, so you don't have to worry about that. You can use your immutable object freely without having fear that the method in which you are passing them will change it.
when we are performing a multithreaded program than this comes handy because bugs based on the data changed by the threads is not supposed to be done
Automatically thread safe
because they cannot be changed (cannot mutate) - any thread accessing it finds the object in same state. So there are no situations like one thread changes state of object, then second thread takes over and changes state of object, then again first one takes over with no clue, that it was changed by someone else
good example is ArrayList - if one thread iterates through its' elements and second thread removes some of them, first thread then throws some kind of concurrency exception. With immutable list this is prevented
Copy constructor
it does not mean that it cannot have a copy constructor. It is a constructor to which you pass object of same type, and you create new object as a copy of given object. It is only a guess, but why would you copy object that is always in a same state?
public class A
{
private int a;
public A(int a)
{
this.a = a;
}
public A(A original)
{
this.a = original.a;
}
}
Implementation of clone
same issue, cloning object, that is always in same state usually only takes space in memory. But you can do it, if you want to create mutable object out of immutable
good example are again collections, you can generate mutable collection out of immutable
Defensive copying
defensive copy means, that when you are setting an object to a field, you create new object of same type which is copy of the original
Example

Immutable objects are thread safe, but why?

Lets say for example, a thread is creating and populating the reference variable of an immutable class by creating its object and another thread kicks in before the first one completes and creates another object of the immutable class, won't the immutable class usage be thread unsafe?
Creating an immutable object also means that all fields has to be marked as final.
it may be necessary to ensure correct behavior if a reference to
a newly created instance is passed from one thread to another without
synchronization
Are they trying to say that the other thread may re-point the reference variable to some other object of the immutable class and that way the threads will be pointing to different objects leaving the state inconsistent?
Actually immutable objects are always thread-safe, but its references may not be.
Confused?? you shouldn't be:-
Going back to basic:
Thread-safe simply means that two or more threads must work in coordination on the shared resource or object. They shouldn't over-ride the changes done by any other thread.
Now String is an immutable class, whenever a thread tries to change it, it simply end up creating a new object. So simply even the same thread can't make any changes to the original object & talking about the other thread would be like going to Sun but the catch here is that generally we use the same old reference to point that newly created object.
When we do code, we evaluate any change in object with the reference only.
Statement 1:
String str = "123"; // initially string shared to two threads
Statement 2:
str = str+"FirstThread"; // to be executed by thread one
Statement 3:
str=str+"SecondThread"; // to be executed by thread two
Now since there is no synchronize, volatile or final keywords to tell compiler to skip using its intelligence for optimization (any reordering or caching things), this code can be run in following manner.
Load Statement2, so str = "123"+"FirstThread"
Load Statement3, so str = "123"+"SecondThread"
Store Statement3, so str = "123SecondThread"
Store Statement2, so str = "123FirstThread"
and finally the value in reference str="123FirstThread" and for sometime if we assume that luckily our GC thread is sleeping, that our immutable objects still exist untouched in our string pool.
So, Immutable objects are always thread-safe, but their references may not be. To make their references thread-safe, we may need to access them from synchronized blocks/methods.
In addition to other answers posted already, immutable objects once created, they cannot be modified further. Hence they are essentially read-only.
And as we all know, read-only things are always thread-safe. Even in databases, multiple queries can read same rows simultaneously, but if you want to modify something, you need exclusive lock for that.
Immutable objects are thread safe, but why?
An immutable object is an object that is no longer modified once it has been constructed. If in addition, the immutable object is only made accessible to other thread after it has been constructed, and this is done using proper synchronization, all threads will see the same valid state of the object.
If one thread is creating populating the reference variable of the immutable class by creating its object and at the second time the other thread kicks in before the first thread completes and creates another object of the immutable class, won't the immutable class usage be thread unsafe?
No. What makes you think so? An object's thread safety is completely unaffected by what you do to other objects of the same class.
Are they trying to say that the other thread may re-point the reference variable to some other object of the immutable class and that way the threads will be pointing to different objects leaving the state inconsistent?
They are trying to say that whenever you pass something from one thread to another, even if it is just a reference to an immutable object, you need to synchronize the threads. (For instance, if you pass the reference from one thread to another by storing it in an object or a static field, that object or field is accessed by several threads, and must be thread-safe)
Thread safety is data sharing safety, And because in your code you make decisions based on the data your objects hold, the integrity and deterministic behaviour of it is vital. i.e
Imagine we have a shared boolean instance variable across two threads that are about to execute a method with the following logic
If flag is false, then I print "false" and then I set the flag back to true.
If flag is true, then I print "true" and then I set the flag back to false.
If you run continuously in a single thread loop, you will have a deterministic output which will look like:
false - true - false - true - false - true - false ...
But, if you ran the same code with two threads, then, the output of your output is not deterministic anymore, the reason is that the thread A can wake up, read the flag, see that is false, but before it can do anything, thread B wakes up and reads the flag, which is also false!! So both will print false... And this is only one problematic scenario I can think of... As you can see, this is bad.
If you take out the updates of the equation the problem is gone, just because you are eliminating all the risks associated with data sync. that's why we say that immutable objects are thread safe.
It is important to note though, that immutable objects are not always the solution, you may have a case of data that you need to share among different threads, in this cases there are many techniques that go beyond the plain synchronization and that can make a whole lot of difference in the performance of your application, but this is a complete different subject.
Immutable objects are important to guarantee that the areas of the application that we are sure that don't need to be updated, are not updated, so we know for sure that we are not going to have multithreading issues
You probably might be interested in taking a look at a couple of books:
This is the most popular: http://www.amazon.co.uk/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1329352696&sr=8-1
But I personally prefer this one: http://www.amazon.co.uk/Concurrency-State-Models-Java-Programs/dp/0470093552/ref=sr_1_3?ie=UTF8&qid=1329352696&sr=8-3
Be aware that multithreading is probably the trickiest aspect of any application!
Immutability doesn't imply thread safety.In the sense, the reference to an immutable object can be altered, even after it is created.
//No setters provided
class ImmutableValue
{
private final int value = 0;
public ImmutableValue(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
public class ImmutableValueUser{
private ImmutableValue currentValue = null;//currentValue reference can be changed even after the referred underlying ImmutableValue object has been constructed.
public ImmutableValue getValue(){
return currentValue;
}
public void setValue(ImmutableValue newValue){
this.currentValue = newValue;
}
}
Two threads will not be creating the same object, so no problem there.
With regards to 'it may be necessary to ensure...', what they are saying is that if you DON'T make all fields final, you will have to ensure correct behavior yourself.

Guava MapMaker optionally set maximumSize(0) for factory method?

I'm using the MapMaker to implement caching of data objects in my application:
public class DataObjectCache<DO extends MyDataObject> {
private final ConcurrentMap<String, DO> innerCache;
public DataObjectCache(Class<DO> doClass) {
Function<String, DO> loadFunction = new Function<String, DO>() {
#Override
public DO apply(String id) {
//load and return DO instance
}
};
innerCache = new MapMaker()
.softValues()
.makeComputingMap(loadFunction);
}
private DO getDataObject(String id) {
return innerCache.get(id);
}
private void putDataObject(DO dataObject) {
innerCache.putIfAbsent(dataObject.getID(), dataObject);
}
}
One of these DataObjectCaches would be instantiated for each data object class, and they would be kept in a master Map, using the Class objects as keys.
There's a minority of data object classes whose instances I don't want cached. However I would still like them to be instantiated by the same code, which the Function is calling, and would still need concurrency in regard to loading them distinctly.
In these cases, I'm wondering if I can just set the maximum size of the map to 0, so that entries are evicted immediately, but still take advantage of the atomic computing aspects of the map. Is this a good idea? Inefficient?
EDIT:
I realized that if I evicted entries immediately after loading them, there's no way to guarantee they are distinctly loaded - if the Map isn't keeping track of them, multiple instances of an object with the same ID could be floating around the environment. So instead of doing this, I think I'll use weak values instead of soft values for the types of objects I don't want taking up cache - let me know if anyone has an opinion on this.
In light of your edit, it sounds like what you're looking for is an interner. An interner returns a representative instance; the same object will be returned by Interner.intern for all objects that are equal according to your equals method. From the Javadoc:
Chooses and returns the representative
instance for any of a collection of
instances that are equal to each
other. If two equal inputs are given
to this method, both calls will return
the same instance. That is,
intern(a).equals(a) always holds, and
intern(a) == intern(b) if and only if
a.equals(b). Note that intern(a) is
permitted to return one instance now
and a different instance later if the
original interned instance was
garbage-collected.
See http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Interner.html and http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Interners.html
That said, it depends what you mean when you say you don't want it cached. If you truly want to return a fresh instance every time, then you'd have to have multiple instances of equivalent objects "floating around".
Interning is holding on to an instance (so it can return the same one), so it is still sort of a cache. I would want to know why you want to avoid caching. If it is because of the size of the objects, you can use a weak interner; the instance will be available for GC when it's no longer referenced. Then again, simply using a MapMaker map with weak values would accomplish that as well.
If, on the other hand, the reason you don't want to cache is because your data is liable to change, interning could be your answer. I would imagine what you'd want is to retrieve the object every time, and then intern it. If the object is equal to the cached one, the interner would simply return the existing instance. If it is different, the interner would cache the new one. Your responsibility then would be to write an equals method on your object that meets the requirements for using a new vs interned instance.
Well, MapMaker.maximumSize has this line: checkArgument(size > 0, "maximum size must be positive"), which will make this impossible. The expireAfter methods also require positive arguments. It's pretty clear that the API designers didn't want you to use their MapMaker-made maps this way.
That said, I suppose, if you really want to use the cache as a passthrough, you could use an expireAfterWrite of 1 nanosecond. It's a hack, but it would practically have the same effect.

Categories

Resources