Saturday, 5 February 2011

ADVANCE THREAD

Java.util.concurrent package
Quick view on the important interfaces and classes bundled in this package.
Important Interfaces:
  1. ThreadFactory
  2. Executor
  3. ExecutorService
  4. ScheduledExecutorService
  5. Future<E>
  6. Callable<E>
  7. ScheduledFuture<E>
  8. BlockingQueue<V>
  9. ConcurrentMap<V>

Important Classes:
  1. Blocking queue implementation-
  2. ArrayBlockingQueue<v>
  3. LinkedBlockingQueue<V>
  4. PriorityBlockingQueue<v>
  5. SynchronousQueue<v>  
For high degree of concurrency-
  1. ConcurrentHashMap<k,v>
  2. ConcurrentLinkedQueue<v>
For iterator use to avoid ConcurrentModificationException exception-
  1. CopyOnWriteArrayList<>
  2. CopyOnWriteArraySet<>


Conditional Thread-Safety (Synchronized wrapper):
Java 1.2 adressed thread safety by introducing synchronized-collections wrappers, synchronizedMap and synchronizedList, are sometimes called Conditionally thread safe - all individual operations are thread-safe, but sequences of operations where the control flow depends on the results of previous operations may be subject to data races.
The conditional thread safety provided by synchronizedList and synchronizedMap present a hidden hazard -- developers assume that because these collections are synchronized, they are fully thread-safe, and they neglect to synchronize compound operations properly. The result is that while these programs appear to work under light load, under heavy load they may start throwing NullPointerException or ConcurrentModificationException.

Thread-Safety By immutability (CopyOnWriteArrayList and CopyOnWriteArraySet):
If you are using an ordinary ArrayList to store a list of listeners, as long as the list remains mutable and may be accessed by multiple threads, you must either lock the entire list during iteration or clone it before iteration, both of which have a significant cost. CopyOnWriteArrayList instead creates a fresh copy of the list whenever a mutative operation is performed, and its iterators are guaranteed to return the state of the list at the time the iterator was constructed and not throw a ConcurrentModificationException.
The CopyOnWriteArrayList class is intended as a replacement for the ArrayList in concurrent applications where traversals greatly outnumber insertions or removals. It helps to get all the thread-safety benefits of immutability without the need for locking.
ConcurrentHashMap:
ConcurrentHashMap is designed to optimize retrieval operations; in fact, successful get() operations usually succeed with no locking at all. Achieving thread-safety without locking is tricky and requires a deep understanding of the details of the Java Memory Model.
“ConcurrentHashMap achieves higher concurrency by slightly relaxing the promises it makes to callers. A retrieval operation will return the value inserted by the most recent completed insert operation, and may also return a value added by an insertion operation that is concurrently in progress (but in no case will it return a nonsense result). Iterators returned byConcurrentHashMap.iterator() will return each element once at most and will not ever throwConcurrentModificationException, but may or may not reflect insertions or removals that occurred since the iterator was constructed. No table-wide locking is needed (or even possible) to provide thread-safety when iterating the collection.ConcurrentHashMap may be used as a replacement for synchronizedMap or Hashtable in any application that does not rely on the ability to lock the entire table to prevent updates.”
Imp Note:
1.    Unlike HashMap and like HashTable, CocurrentHashMap does not allow null key, as it has been derived with intension to make compatible to HashMap and HashTable both.
2.    The related ConcurrentReaderHashMap class offers similar multiple-reader concurrency, but allows only a single active writer.
3.    This class supports a hard-wired preset concurrency level of 32. This allows a maximum of 32 put and/or remove operations to proceed concurrently. This level is an upper bound on concurrency
**Interesting : Why ConcurrentHashmap but no ConcurrentHashSet**
There is NOT any support for locking the entire table to prevent updates. This makes it impossible, for example, to add an element only if it is not already present, since another thread may be in the process of doing the same thing. If you need such capabilities, consider instead using the ConcurrentReaderHashMap class.
Blocking Queues and implementations:
A blocking queue is a queue that blocks when you try to dequeue from it and the queue is empty, or if you try to enqueue items to it and the queue is already full. A thread trying to dequeue from an empty queue is blocked until some other thread inserts an item into the queue. A thread trying to enqueue an item in a full queue is blocked until some other thread makes space in the queue, either by dequeuing one or more items or clearing the queue completely.  All BlockingQueue implementations are threadsafe.
  • A ConcurrentLinkedQueue is an appropriate choice when many threads will share access to a common collection. This queue does not permit null elements. This queue orders elements FIFO (first-in-first-out)
  • ArrayBlockingQueue is a classic "bounded buffer", in which a fixed-sized array holds elements inserted by producers and extracted by consumers. This class supports an optional fairness policy for ordering waiting producer and consumer threads. This queue orders elements FIFO (first-in-first-out). 
  • LinkedBlockingQueue typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.
  • PriorityBlockingQueue relying on natural ordering also does not permit insertion of non-comparable objects (doing so results in ClassCastException).
  • A synchronous queue does not have any internal capacity, not even a capacity of one. You cannot peek at a synchronous queue because an element is only present when you try to take it; you cannot add an element (using any method) unless another thread is trying to remove it; you cannot iterate as there is nothing to iterate

Difference between blocking queue implementations like:
ArrayBlockingQueue, LinkedBlockingQueue and ConcurrentLinkedQueue-

Basically the differences between them are performance characteristics and blocking behavior.
Taking the easiest first, ArrayBlockingQueue is a queue of a fixed size. So if you set the size at 10, and attempt to insert an 11th element, the insert statement will block until another thread removes an element. The fairness issue is what happens if multiple threads try to insert and remove at the same time (in other words during the period when the Queue was blocked). A fairness algorithm ensures that the first thread that asks is the first thread that gets. Otherwise, a given thread may wait longer than other threads, causing unpredictable behavior (sometimes one thread will just take several seconds because other threads that started later got processed first). The trade-off is that it takes overhead to manage the fairness, slowing down the throughput.

The most important difference between LinkedBlockingQueue and ConcurrentLinkedQueue is that if you request an element from a LinkedBlockingQueue and the queue is empty, your thread will wait until there is something there. A ConcurrentLinkedQueue will return right away with the behaviour of an empty queue.

Which one depends on if you need the blocking, Where you have many producers and one consumer, it sounds like it. On the other hand, where you have many consumers and only one producer, you may not need the blocking behaviour, and may be happy to just have the consumers check if the queue is empty and move on if it is.

Annexure Links:
http://www.ibm.com/developerworks/java/library/j-jtp07233.html

How Vector / HashTable are thread Safe?


java.util.Hashtable and java.util.Vector are two examples of JDK objects whose every method is synchronized. This imposes a large runtime cost on applications that iterate over these structures. When you are not using threads, prefer java.util.HashMap and java.util.ArrayList. Thread.sleep(5000) is supposed to sleep for 5 seconds. However, if somebody changes the system time, you may sleep for a very long time or no time at all. The OS records the wake up time in absolute form, not relative.


No comments:

Post a Comment