• No se han encontrado resultados

2 Fundamento teórico

2.13. TRATAMIENTO ENDOSCÓPICO

If a single thread uses more than one protected shared resource, then we should make sure that we acquire shared resources in particular order and release them in reverse order, otherwise we might end up into a deadlock scenario.

Q 165. Are there concurrent version for TreeMap and TreeSet in Java Collections

Framework?

Java Collection Framework have ConcurrentSkipListMap and ConcurrentSkipListSet which are concurrent replacement for TreeMap and TreeSet. These classes implement SortedMap and SortedSet interface respectively. So if our application demands fair concurrency then instead of wrapping TreeMap and TreeSet inside synchronized collection, we can prefer these concurrent utilities. These also implement NavigableMap and NavigableSet interface with methods like lowerKey, floorKey, ceilingKey, higherKey, headMap and tailMap. Concurrent vs Synchronized version

Key Point to note here is that there is difference between synchronized version of TreeMap and Concurrent version of TreeMap (ConcurrentSkipListMap). Synchronized allows just one thread at a time i.e. access to the sharedobject is serialized, thus throughput will be low. But Insertion, removal, update, and access operations can be safely execute concurrently by multiple threads in case of ConcurrentSkipListMap. There is underlying difference in the implementation of ConcurrentSkipListMap to support this. Same is the case with synchronized and concurrent version of TreeSet. Thus care must be taken while designing scalable concurrent applications and preference should be given to concurrent versions.

Time Complexity

Average time complexity is log(n) for the containsKey, get, put, remove ad the variant operations of the ConcurrentSkipListMap

Q 166. Is it safe to iterate over an ArrayList and remove its elements at the same time

? When do we get ConcurrentModificationException & hidden Iterator?

Iterator returned by the ArrayList (and many other collection types) is fail-fast. If the list is structurally modified at anytime after the iterator is created, in any way except through the Iterator's own remove() method, the iterator will throw ConcurrentModificationException and thus fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Structural Modification

“A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely changing the values associated with a key that an instance already contains is not a structural modification.” - Java Docs

Further, the structural modification could happen either from single thread or from multiple threads. The behavior of ArrayList would be different in both the cases as mentioned below.

Single Threaded Scenario

Never call list.remove(element) to remove a item from list while traversing it. Rather use Iterator.remove() mehtod.

private List<String> list = new ArrayList<>(asList("first", "second", "third", "fourth")); public void unsafeMethod() {

for (String item : list) { // Will throw ConcurrentModificationException

list.remove(item); }

}

public void safeMethod() {

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) { // safe to call iterator.remove()

String item = iterator.next(); iterator.remove();

} }

Multi-Threading Scenario

ArrayList implementation is not thread-safe because it provides no synchronization mechanism for protecting the shared state of its fields. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the list.

If no such object exists, the list should be "wrapped" using the Collections.synchronizedList() method. This is best done at creation time, to prevent accidental unsynchronized access to the list :

List list = Collections.synchronizedList(new ArrayList(...)); public void safeMethod() {

synchronized(list) {

...rest of the code as shown in previous method }

Hidden Iterators

There are certain ArrayList methods which uses Iterators in a hidden form the API user. size() and toString() are few of them. So care must be taken to call these methods from synchronized block in case of multi- threaded scenario.

List<String> names = new ArrayList(asList("munish","ravneesh", "rajneesh")); names.removeIf(name -> "munish".equalsIgnoreCase(name));

System.out.println("names = " + names);

Though lambda makes removal quite compact, but the operation is not thread-safe and must not be used in multi-threaded environment without explicit synchronization in place.

Q 167. What is ThreadLocal class, how does it help writing multi-threading code? any

usage with example?

ThreadLocal class provides a simple mechanism for thread safety by creating only one object instance per thread. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID). Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist)

ThreadLocal is used to achieve thread-safety in our multi-threaded code by creating a copy local to a thread and thus no more sharing of state.

When get() method is invoked the first time, ThreadLocal calls initialValue() and returns the newly created Object, the same Object is returned on subsequent invocations by the same thread untill we clear the Object. ThreadLocal Usage Scenarios

• EntityManager in JPA - EntityManager instance is not thread safe but creating too many EntityManagers could be expensive, thus in a servlet environment ThreadLocal copy could be created using a servlet Filter and re-used the same EntityManager for the whole request life cycle, committing the changes in the end. In this case, when the thread calls get() for the first time, a new EntityManager instance is created and the same is re used on subsequent calls to get() method by the same thread.

public interface SessionCache {

public EntityManager getUnderlyingEntityManager(); }

public class ThreadLocalSession implements SessionCache{ @Override

public EntityManager getUnderlyingEntityManager() { return threadLocalJPASession.get();

}

private static class ThreadLocalJPASession extends ThreadLocal<EntityManager>{ @Override

protected EntityManager initialValue() {

return JPASessionFactory.getInstance().getSession(); }

}

public static final ThreadLocalJPASession threadLocalJPASession = new ThreadLocalJPASession(); public void set(EntityManager em){

threadLocalJPASession.set(em); }

threadLocalJPASession.get().close(); threadLocalJPASession.remove(); }

}

• Using Calendar class in multi-threading environment : Calendar.getInstance() is not safe from multi- threading perspective and a copy of it could be created per thread and stored in ThreadLocal.

• Random Number Generator, ByteBuffers, XML parsers can utilize ThreadLocal for optimization purpose. Three main Criteria for choosing ThreadLocal's applicability

• Object is non-trivial to construct

• Instance of object is frequently needed • Application is multi-threaded

Notes

ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

Q 168. How would you implement your own Transaction Handler in Core Java, using

Documento similar