Sunday, August 13, 2006

Remembering the Tiger (Java 5.0) - Part 1

Before we move onto Java Mustang, let us remember the Tiger! The focus of this part is Multi-threaded programming (usually done in server side applications) with the new features of the Tiger (Java 5.0).

New Multi Threading Features of Tiger Java 5.0

1. New Objects
- StringBuilder Vs. StringBuffer
- Atomic Classes (AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference)

- Concurrent Collection API
- Concurrent Collection - Blocking Queues

2. New Features
- Covariant Return
- Generics


3. Some Optimization Techniques
- Usage of final keyword
- Avoid Enumeration or an Iterator
- Usage of Stack variables when possible
- Minimize Synchronization


4. Threads
- Synchronization Classes (Locks, Barri
er, Semaphore, Countdown Latch, Exchanger & Reader/Writer Locks)
- Thread Pool
- Exception Handling

1. New Objects

StringBuilder

Java Architects / Developers who create high performance multi threaded Java Applications are aware of the cost of creating objects and synchronization
costs. Following is a simple example of unwanted object creation.

String host = new String("Web Server");
String ip = new String("10.10.10.1");
int port = 80;

String displayValue1 = host + " (" + ip + ":" + port + ")";


System.out.println(displayValue1); // Web Server (10.10.10.1:80)

/**
* java.lang.StringBuffer
* The default capacity of StringBuffer is 16 bytes. When the capacity reaches the limit then
* StringBuffer creates a new array (char) doubling the previous size and copies the data to
* the new array. Old array gets discarded at the time garbage collection. Key to optimization
* is creating a StringBuffer with required capacity.

*/

StringBuffer sbuf = new StringBuffer(64);
sbuf.append(host).append(" (").append(ip).append(":").app
end(port).append(")");

String displayValue2 = sbuf.toString();

System.out.println(displayValue2); // Web Server (10.10.10.1:80)


/**
* java.lang.StringBuilder()
* StringBuffer is thread safe. However if your data set is thread local then use StringBuilder
* instead. Avoiding unwanted synchronization improves the performance further.

*/

StringBuilder sbuild = new StringBuilder(64);
sbuild.append(host).append(" (").append(ip).append(":").append(port).append(")");

String displayValue3 = sbuild.toString();

System.out.println(displayValue3); // Web Server (10.10.10.1:80)

Atomic Classes (java.util.concurrent.atomic.*)


From the performance perspective, one of the key objectives of the thread safe programming is shrinking the synchronization scope. When ever we use primitives which need to be shared across the threads we make the primitives volatile or synchronize that section of the code.

Volatile variables can be safely used only for a single read and write operations. It cannot be used for an operation like ++ / -- because it contains multiple operations like read, modify and write while the new Atomic Classes can be used for similar functions atomically. However, these new Atomic Classes require hardware support to make the multiple operations (like read, modify and write) atomic. The hardware guarantees that these operations are atomic.

Compare and Swap (CAS)

Compare and Swap is a special CPU instruction (used in multi processor systems) which takes three values: A memory location (L), expected old value (O) and a new value (N).
The Processor will atomically compare the contents of a memory location to the expected (old) value and if they are same, then it modifies that content to a given new value (N) other wise it will do nothing. However, in either case it returns the value that was at the location prior to the CAS instruction. (Some flavors of CAS will instead simply return whether or not CAS succeeded.)

Intel processors implements CAS by the cmpxchg family of instructions, while MIPS and PowerPC have a pair of instructions. MIPS has “load linked” and “store conditional” while PowerPC has “load and reserve” and “store conditional”.

- AtomicBoolean
- AtomicInteger

- AtomicLong
- AtomicReference


As part of Tiger (Java 5.0) release java introduced Atomic classes like AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference which handle integers, long, Booleans and Objects respectively. These classes allow multiple operations like read, modify and write in a single atomic operation. Most of the functionality in the ReentrantLock class (Mutex) uses Atomic classes for the implementation. Atomic classes can be even used to avoid synchronization at the cost of complex code and design. This functionality is implemented at the native level.

// Testing AtomicInteger Class

AtomicInteger ai = new AtomicInteger(10); // Initialized with value 10

System.out.println("Value Get-And-Set(2) = "+ai.getAndSet(2)); // Displays 10
System.out.println("Value Get() = "+ai.get()); // Displays 2


In the above example getAndSet() method returns the original value (10) before setting the new value as 2. However, as these operations are atomic this doesn’t require any synchronization locks. Similar methods are incrementAndGet(), getAndIncrement(),
decrementAndGet(), getAndDecrement(), addAndGet(), getAndAdd().

The conditional modifier methods compareAndSet() and weakCompareAndSet() takes two arguments – the expected value and the new value. If the current value is not the expected value then new value is discarded and the method returns false else the new value is set and the method returns true. The weakCompareAndSet() returns false then the variable is not set with new value, however, that doesn’t mean that the existing value is not the expected value.

Atomic package also supports Arrays, AtomicIntegerArray, AtomicLongArray and AtomicReferenceArray. You can’t modify the whole array atomically; however, you can modify one indexed variable at a time. There are no implementations for an array of Booleans as this can be achieved by using AtomicIntegerArray.

Other classes in the package to complete this brief overview of the Atomic package are AtomicMarkableReference and AtomicStampedReference. The former maintains an object reference along with a Boolean that can be updated atomically while the latter maintains the object reference with an integer “stamp” that can be updated atomically.


Concurrent Collection API (java.util.concurrent.*)

-
ConcurrentHashMap
-
CopyOnWriteArrayList
- CopyOnWriteArraySet
- ConcurrentLinkedQueue

All the above classes are nearly Thread safe. ConcurrentHashMap uses less synchronization than the Hashtable. CopyOnWriteArray List and Set provides unsynchronized iterator access, while ConcurrentLinkedQueue an unbounded thread safe non blocking FIFO queue.

Concurrent Collection API – Blocking Queues (java.util.concurrent.*)

-
ArrayBlockingQueue (Bounded FIFO Queue)
- DelayQueue (UnBounded Queue with time based order)
- LinkedBlockingQueue (Bounded / UnBounded FIFO Queue)
- PriorityBlockingQueue
-
SynchronousQueue (Bounded FIFO Queue)

All the above classes are thread safe and notifies the thread when the content changes. It implements BlockingQueue interface that allows the threads to wait either if the queue is full (when the thread try to store data) or if the queue is empty (when the thread tries to retrieve data).

2. New Features

Covariant Return

Java 5.0 introduced the concept of covariant return where you can override the return type of a method in a class where the return type is the subclass of the overridden method (of the super class return type). Let me show that using a sample code. The following code shows two vehicle types Car and Van (Van extends from Car).

The following code shows two Vehicle Factory types NormalVehicleFactory and FamilyVehicleFactory (extends from NormalVehicleFactory). However, what’s odd is the getVehicle() method call. The FamilyVehicleFactory overrides the getVehicle() method and return a sub class of Car (which is Van).



3. Some Optimization Techniques

Similar to the usage of StringBuilder and other new Collection API’s, as an Architect / Developer you need to keep in mind on performance optimization techniques to build a scalable performance focused application. This part will be concluded in the next few days…..
10. Sun Microsystem – Untangling the Threads
Books

1. Addison-Wesley (May 9, 2006) –
Java Concurrency in Practice By Brian Goetz
2. O’Reilly (Sept 13, 2004) – Java Threads (3rd Edition) By Scot Oaks & Henry Wong
3. O’Reilly (June 25, 2004)– Java 5.0 Tiger A Developers Notebook By B McLaughlin, D Flanagan
4. Addison-Wesley (Feb 4, 2000) –
Practical Java By Peter Haggar

(Part 2 of this series will focus on Threads and new Synchronization techniques...)