Abstract: Concurrency is easier when we work with immutable objects. In this newsletter, we define another concurrency law, The Law of the Xerox Copier, which explains how we can work with immutable objects by returning copies from methods that would ordinarily modify the state.
Welcome to the 176th issue of The Java(tm) Specialists' Newsletter, sent to you from Oslo in Norway. The JavaZone conference is wonderful, with at least one interesting topic per session. There are actually two other talks I'd like to attend when I am speaking tomorrow ...
Thanks for the feedback after my last newsletter, where I showed how to construct objects without calling any constructor. When I wrote the article, I felt it unnecessary to explicitly state that making a linkage to sun.* classes would be a problem for portability of your code, since that is rather obvious. So there, I've said it ... :-)
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
In previous newsletters, we looked at a series of laws to make sense of Java concurrency. Just to remind you, here they are again. In this newsletter, I would like to add a new one to our list, the Law of the Xerox Copier.
At the end of 2008, we found a beautiful house in Crete that we wanted to purchase. We only had one tiny little problem. Houses in general are kind of expensive and I didn't have all that much in my wallet. So we started the long process of begging banks for a loan, which involves giving them reams of paperwork.
You would imagine that it is safe to give a bank your documents, expecting them to look after them until they returned them. Well, the night before the bank was supposed to give back our paperwork, loan denied of course, they were attacked by a mob of angry protesters who completely trashed it, together with our documents. How often does an event like that happen? Fortunately, we had protected our original objects by only giving copies to the loan consultant.
Coming back to concurrency, it is usually a good idea to make your objects as immutable as possible. Instead of then changing the object, we would return a new copy containing the changes.
Immutable objects are always thread safe. We cannot have stale values, race conditions or early writes. According to Brian Goetz, an immutable class is defined as the following:
An example of an immutable class is String. Whenever we "modify" it, such as with the + operator or the toUpperCase() method. This causes additional work for the garbage collector, but concurrency is much easier.
In Scala [ISBN 0981531601] , we even have immutable lists. How could that work in Java? Here is an example:
import java.util.Iterator; public class ImmutableArrayList<E> implements Iterable<E> { private final Object[] elements; public ImmutableArrayList() { this.elements = new Object[0]; } private ImmutableArrayList(Object[] elements) { this.elements = elements; } public int size() { return elements.length; } public ImmutableArrayList<E> add(E e) { Object[] new_elements = new Object[elements.length + 1]; System.arraycopy(elements, 0, new_elements, 0, elements.length); new_elements[new_elements.length - 1] = e; return new ImmutableArrayList<E>(new_elements); } public Iterator<E> iterator() { return new Iterator<E>() { private int pos = 0; public boolean hasNext() { return pos < elements.length; } public E next() { return (E) elements[pos++]; } public void remove() { throw new UnsupportedOperationException(); } }; } }
Making ArrayList immutable is probably going overboard, a better approach might be to just use the CopyOnWriteArrayList, which also gives us great concurrent performance.
We can use this ImmutableArrayList in a more functional coding approach:
public class ImmutableArrayListTest { public static void main(String[] args) { ImmutableArrayList<String> ial = new ImmutableArrayList<String>(); ial = ial.add("Heinz").add("Max").add("Kabutz"); for (Object obj : ial) { System.out.println(obj); } } }
Making copies of objects has helped me out of a fix many times in the past, where rather complicated concurrency bugs would have been tricky to resolve otherwise.
Kind regards from Oslo
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.