Multi Threading Java Interview Questions | Eklavya Online

Multi Threading Java Interview Questions

This deals with concurrent programming. The wait() and notify() methods are designed to provide a mechanism to allow a thread to be block until a specific condition is met.

However, java.util.concurrent should be used instead of wait() and notify() to reduce complexity.

// Sort

Collections.sort(list);

// Sort case-insensitive

Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

// SortReverse-order

Collections.sort(list, Collections.reverseOrder ());

// Reverse-order sort case-insensitive

Define local, member and a class variable.

Within a method variables declared are called “local” variables.

Variables declared in the class i.e not in any methods are “member” variables (global variables).

Variables declared in the class i.e not in any methods and are called as “static” are class variables.

Name the different identifier states of a Thread.

Different types of identifiers of a Thread are:

R – Running or runnable thread

S – Suspended thread

CW – Thread waiting on a condition variable

MW – Thread waiting on a monitor lock

MS – Thread suspended waiting on a monitor lock

Define Vector class? Differentiate the Vector and ArrayList.

Vector canbe said a legacy class which has been introduced to implement the List interface since Java 2 platform v1.2

Vector is always synchronized but ArrayList is not.

When Vector class is synchronized, if we will run in multithreading environment we’ve to use ArrayList with Collections.

Vector has a default size i.e 10 while arrayList has no default size.

ArraayList is not having any method returning Enumerations where as vector list is having.

Differentiate between Enumeration and Iterator interface

In java.util package the Enumeration and Iterator are available.

The Enumeration interface is replicated by the Iterator interface.

In preference to Enumeration new implementations should consider using Iterator .

 

The difference of Iterators from enumerations are:

  • Enumeration has 2 methods namely hasMoreElements() & nextElement() where the Iterator contained three methods namely hasNext(), next(),remove().
  • An optional remove operation is added in Iterator,and has shorter method names. We Use remove() to delete the objects but the Enumeration interface does not support this feature.
  • The legacy classes use Enumeration interface .Vector.elements() & Hashtable.elements() method results Enumeration.
  • All Java Collections Framework classes returns iterator. java.util.Collection.iterator() method returning an instance of Iterator.

Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

Collections.reverse(list);

A thread class may be declared as a subclass of Thread, or it may implement the Runnable interface

The server has multiple threads that are available to handle requests. When a request comes in, it is assigned to a thread, which calls a service method (for example: doGet(), doPost() and service()) of the servlet. For this reason, a single servlet object can have its service methods called by many threads at once.

When two threads are waiting each other and can’t precede the program is said to be deadlock

If a thread attempts to execute a synchronized method or synchronized statement and is unable to acquire an object’s lock, it enters the waiting state until the lock becomes available

?– Multithreading is the mechanism in which more than one thread run independent of each other within the process. wait (), notify () and notifyAll() methods can be used for inter-thread communication and these methods are in Object class. wait() : When a thread executes a call to wait() method, it surrenders the object lock and enters into a waiting state. notify() or notifyAll() : To remove a thread from the waiting state, some other thread must make a call to notify() or notifyAll() method on the same object.

Daemon thread is a low priority thread which runs intermittently in the back ground doing the garbage collection operation for the java runtime system. setDaemon method is used to create a daemon thread

The high-level thread states are ready, running, waiting, and dead.

With respect to multithreading, synchronization is the capability to control the access of multiple threads to shared resources. Without synchronization, it is possible for one thread to modify a shared object while another thread is in the process of using or updating that object’s value. This often leads to significant errors.

An object’s lock is a mechanism that is used by multiple threads to obtain synchronized access to the object. A thread may execute a synchronized method of an object only after it has acquired the object’s lock.

All objects and classes have locks. A class’s lock is acquired on the class’s Class object.

All tasks must implement the run() method, whether they are a subclass of Thread or implement theRunnable interface.

An executing thread is in the running state.

Thread class and Runnable interface can be used to create threads and using Runnable interface is the most advantageous method to create threads because we need not extend thread class here.

Finally is the block of code that executes always. The code in finally block will execute even if an exception is occurred. Finally block is NOT called in following conditions

  • If the JVM exits while the try or catch code is being executed, then the finally block may not execute. This may happen due to System.exit() call.
  • if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
  • If a exception is thrown in finally block and not handled then remaining code in finally block may not be executed.

A Java object is considered immutable when its state cannot change after it is created. Use of immutable objects is widely accepted as a sound strategy for creating simple, reliable code. Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state. java.lang.String and java.lang.Integer classes are the Examples of immutable objects from the Java Development Kit. Immutable objects simplify your program due to following characteristics :

  • Immutable objects are simple to use test and construct.
  • Immutable objects are automatically thread-safe.
  • Immutable objects do not require a copy constructor.
  • Immutable objects do not require an implementation of clone.
  • Immutable objects allow hashCode to use lazy initialization, and to cache its return value.
  • Immutable objects do not need to be copied defensively when used as a field.
  • Immutable objects are good Map keys and Set elements (Since state of these objects must not change while stored in a collection).
  • Immutable objects have their class invariant established once upon construction, and it never needs to be checked again.

Immutable objects 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

A thread can enter the waiting state by invoking its sleep() method, by blocking on I/O, by unsuccessfully attempting to acquire an object’s lock, or by invoking an object’s wait() method. It can also enter the waiting state by invoking its (deprecated) suspend() method.

The operating system’s task scheduler allocates execution time to multiple tasks. By quickly switching between executing tasks, it creates the impression that tasks execute sequentially.

When a window is repainted by the AWT painting thread, it sets the clipping regions to the area of the window that requires repainting.

The runtime system keeps track of the memory that is allocated and is able to

determine whether that memory is still useable. This work is usually done in

background by a low-priority thread that is referred to as garbage collector. When the

gc finds memory that is no longer accessible from any live thread it takes steps to

release it back to the heap for reuse

When a thread terminates its processing, it enters the dead state.

Garbage collection is the process of automatically freeing objects that are no longer referenced by the program. This frees the programmer from having to keep track of when to free allocated memory, thereby preventing many potential bugs. Thus making programmers more productive as they can now put more effort in coding rather than worrying about memory management.

The only disadvantage of garbage collector is it adds overheads. Because the JVM (Java virtual machine) has to keep a constant track of the objects which are not referenced and then free these unreferenced objects on fly. This whole process has a slight impact on the application performance. But garbage collector has a good algorithm and it runs in its own thread thus having a least impact on the application performance but still it has some impact.

The wait(), notify(), and notifyAll() methods are used to provide an efficient way for threads to wait for a shared resource. When a thread executes an object’s wait() method, it enters the waiting state. It only enters the ready state after another thread invokes the object’s notify() or notifyAll() methods..

Thread contains ready, running, waiting and dead states.

The main difference between the three most commonly used String classes as follows.

  • StringBuffer and StringBuilder objects are mutable whereas String class objects are immutable.
  • StringBuffer class implementation is synchronized while StringBuilder class is not synchronized.
  • Concatenation operator “+” is internally implemented by Java using either StringBuffer or StringBuilder.
  • Criteria to choose among String, StringBuffer and StringBuilder
  • If the Object value will not change in a scenario use String Class because a String object is immutable.
  • If the Object value can change and will only be modified from a single thread, use a StringBuilder because StringBuilder is unsynchronized(means faster).
  • If the Object value may change, and can be modified by multiple threads, use a StringBuffer because StringBuffer is thread safe(synchronized).

Vector / HashTable are synchronized which means they are thread safe. Cost of thread safe is performance degradation. So if you are sure that you are not dealing with huge number of threads then you should use ArrayList / HashMap.But yes you can stillsynchronize List and Map’s using Collections provided methods :-

  • List OurList = Collections.synchronizedList (OurList);
  • Map OurMap = Collections.synchronizedMap (OurMap);

A thread enters the waiting state when it blocks on I/O.

Synchronization is the mechanism that ensures that only one thread is accessed the resources at a time.

The paint() method supports painting via a Graphics object. The repaint() method is used to causepaint() to be invoked by the AWT painting thread.

After a thread is started, via its start() method or that of the Thread class, the JVM invokes the thread’srun() method when the thread is initially executed.

A thread is in the ready state after it has been created and started.

A dead thread cannot be restarted.

Synchronized methods are methods that are used to control access to an object. A thread only executes a synchronized method after it has acquired the lock for the method’s object or class.

Synchronized statements are similar to synchronized methods. A synchronized statement can only be executed after a thread has acquired the lock for the object or class referenced in the synchronized statement.

The finally clause of the try-catch-finally statement is always executed unless the thread of execution terminates or an exception occurs within the execution of the finally clause.

The marker interface is a design pattern, used with languages that provide run-time type information about objects. It provides a way to associate metadata with a class where the language does not have explicit support for such metadata. To use this pattern, a class implements a marker interface, and code that interact with instances of that class test for the existence of the interface. Whereas a typical interface specifies methods that an implementing class must support, a marker interface does not do so. The mere presence of such an interface indicates specific behavior on the part of the implementing class. There can be some hybrid interfaces, which both act as markers and specify required methods, are possible but may prove confusing if improperly used. Java utilizes this pattern very well and the example interfaces are:

  • io.Serializable – Serializability of a class is enabled by the class implementing the java.io.Serializable interface. The Java Classes that do not implement Serializable interface will not be able to serialize or deserializ their state. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
  • rmi.Remote – The Remote interface serves to identify interfaces whose methods may be invoked from a non-local virtual machine. Any object that is a remote object must directly or indirectly implement this interface. Only those methods specified in a “remote interface”, an interface that extends java.rmi.Remote are available remotely.
  • lang.Cloneable – A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class. Invoking Object’s clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
  • servlet.SingleThreadModel – Ensures that servlets handle only one request at a time. This interface has no methods.
  • util.EvenListener – A tagging interface that all event listener interfaces must extend.
  • The “instanceof” keyword in java can be used to test if an object is of a specified type. So this keyword in combination with Marker interface can be used to take different actions based on type of interface an object implements.

It is very useful to have strings implemented as final or immutable objects. Below are some advantages of String Immutability in Java

  • Immutable objects are thread-safe. Two threads can both work on an immutable object at the same time without any possibility of conflict.
  • Security: the system can pass on sensitive bits of read-only information without worrying that it will be altered
  • You can share duplicates by pointing them to a single instance.
  • You can create substrings without copying. You just create a pointer into an existing base String guaranteed never to change. Immutability is the secret that makes Java substring implementation very fast.
  • Immutable objects are good fit for becoming Hashtable keys. If you change the value of any object that is used as a hash table key without removing it and re-adding it you will lose the object mapping.
  • Since String is immutable, inside each String is a char[] exactly the correct length. Unlike a StringBuilder there is no need for padding to allow for growth.
  • If String were not final, you could create a subclass and have two strings that look alike when “seen as Strings”, but that are actually different.

When a task’s interrupt() method is executed, the task enters the ready state. The next time the task enters the running state, an InterruptedException is thrown

An uncaught exception results in the uncaughtException() method of the thread’s ThreadGroup being invoked, which eventually results in the termination of the program in which it is thrown.

?– When you expect your code will be accessed by different threads and these threads may change a particular data causing data corruption.

The start() method of the Thread class is invoked to cause an object to begin executing as a separate thread.

Threads block on I/O (that is enters the waiting state) so that other threads may execute while the I/O Operation is performed.

Applets are small applications that are accessed from web server automatically installed, and run from the browser. Once an applet arrives on the client it has limited access to resources thus ensuring security for the end user. An applet is controlled by the software that runs it. Usually, the underlying software is a browser, but it can also be applet viewer. If you run the applet source code from eclipse it runs inside an applet viewer. All applets should inherit from applet class.

Below are sequences of events which occur in applet:

  • The init Method: The init method is called when the applet is first loaded. Init method can be used to initialize color, fonts or any type of one type operation needed for the applet.
  • The start Method: The start method is called when user visits a browser with an applet on it. In start method applet spawns a thread in which it runs the paint method.
  • paint() is called every time when applet has to re-display everything.

Process is a program in execution whereas thread is a separate path of execution in a program

Best practices relating to Java Collection framework are as follow:

  • Choose the right type of data structure based on usage patterns like fixed size or required to grow, duplicates allowed or not, ordering is required to be maintained or not, traversal is forward only or bi-directional, inserts at the end only or any arbitrary position, more inserts or more reads, concurrently accessed or not, modification is allowed or not, homogeneous or heterogeneous collection, etc. Also, keep multi-threading, atomicity, memory usage and performance considerations discussed earlier in mind.
  • Don’t assume that your collection is always going to be small as it can potentially grow bigger with time. So your collection should scale well.
  • Program in terms of interface not implementation: For example, you might decide a LinkedList is the best choice for some application, but then later decide ArrayList might be a better choice for performance reason.
    • Bad:
      • ArrayList list = new ArrayList(100);
    • Good:

// program to interface so that the implementation can change

  • List list = new ArrayList(100);
  • List list2 = new LinkedList(100);
  • Return zero length collections or arrays as opposed to returning a null in the context of the fetched list is actually empty. Returning a null instead of a zero length collection is more error prone, since the programmer writing the calling method might forget to handle a return value of null.
    • List emptyList = Collections.emptyList( );
    • Set emptySet = Collections.emptySet( );
  • Use generics for type safety, readability, and robustness.
  • Encapsulate collections: In general, collections are not immutable objects. So care should be taken not to unintentionally expose the collection fields to the caller. The caller may not perform any necessary validation.

The basic difference between a Vector and an ArrayList is that, vector is synchronized while ArrayList is not. Thus whenever there is a possibility of multiple threads accessing the same instance, one should use Vector. While if not multiple threads are going to access the same instance then use ArrayList. Non synchronized data structure will give better performance than the synchronized one.

Vector & ArrayList both classes are implemented using dynamically resizable arrays, providing fast random access and fast traversal. ArrayList and Vector class both implement the List interface. Both the classes are member of Java collection framework, therefore from an API perspective, these two classes are very similar. However, there are still some major differences between the two. Below are some key differences

  • Vector is a legacy class which has been retrofitted to implement the List interface since Java 2 platform v1.2

Vector is synchronized whereas ArrayList is not. Even though Vector class is synchronized, still when you want programs to run in multithreading There are multiple aspects to this decision:

  • The basic difference between a Hashtable and an HashMap is that, Hashtable is synchronized while HashMap is not. Thus whenever there is a possibility of multiple threads accessing the same instance, one should use Hashtable. While if not multiple threads are going to access the same instance then use HashMap. Non synchronized data structure will give better performance than the synchronized one.
  • If there is a possibility in future that – there can be a scenario when you may require to retain the order of objects in the Collection with key-value pair then HashMap can be a good choice. As one of HashMap’s subclasses is LinkedHashMap, so in the event that you’d want predictable iteration order (which is insertion order by default), you can easily swap out the HashMap for a LinkedHashMap. This wouldn’t be as easy if you were using Hashtable. Also if you have multiple thread accessing you HashMap then Collections.synchronizedMap() method can be leveraged. Overall HashMap gives you more flexibility in termsenvironment using ArrayList with Collections.synchronizedList() is recommended over Vector.
  • ArrayList has no default size while vector has a default size of 10.
  • The Enumerations returned by Vector’s elements method are not fail-fast. Whereas ArraayList does not have any method returning Enumerations.

Both Iterator and Enumeration are used to traverse Collection objects, in a sequential fashion. Enumeration can be applied to Vector and HashTable. Iterator can be used with most of the Collection objects. The main difference between the two is that Iterator is fail-safe. i.e,  If you are using an iterator to go through a collection you can be sure of no concurrent modifications in the underlying collection which may happen in multi-threaded environments.

  • Hashtableis synchronized, whereas HashMap is not. This makes HashMap better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.
  • Hashtabledoes not allow null keys or values. HashMap allows one null key and any number of null values.

One of HashMap’s subclasses is LinkedHashMap, so in the event that you’d want predictable iteration order (which is insertion order by default), you could easily swap out the HashMap for aLinkedHashMap. This wouldn’t be as easy if you were using Hashtable

In Java, memory leaks are possible under a number of scenarios. Here is a typical example where hashCode( ) and equals( ) methods are not implemented for the Key class that is used to store key/value pairs in a HashMap.

This will end up creating a large number of duplicate objects. All memory leaks in Java end up with java.lang.OutOfMemoryError, and it is a matter of time. The following code agressively creates the OutOfMemoryError via an endless loop for demonstration purpose.

If you are not familiar with the significance of equals( ) and hashCode ( ) methods in Java, then learn with this example how to define proper key class in Java.

import java.util.HashMap;

import java.util.Map;

 

public class MemoryLeak {

 

public static void main(String[] args) {

Map<Key, String> map = new HashMap<Key, String>(1000);

 

int counter = 0;

while (true) {       // creates duplicate objects due to bad Key class

map.put(new Key(“dummyKey”), “value”);

counter++;

if (counter % 1000 == 0) {

System.out.println(“map size: ” + map.size());

System.out.println(“Free memory after count ” + counter + ” is ” + getFreeMemory() + “MB”);

 

sleep(1000);

}

}

}

 

 

// inner class key without hashcode() or equals() — bad implementation

 

static class Key {

private String key;

 

public Key(String key) {

this.key = key;

}

 

}

 

//delay for a given period in milli seconds

 

public static void sleep(long sleepFor) {

try {

Thread.sleep(sleepFor);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

//get available memory in MB

public static long getFreeMemory() {

return Runtime.getRuntime().freeMemory() / (1024 * 1024);

}

 

}

 

If you run the above code, you will get the ouput as shown below

map size: 1000

Free memory after count 1000 is 4MB

map size: 2000

Free memory after count 2000 is 4MB

map size: 1396000

Free memory after count 1396000 is 2MB

map size: 1397000

Free memory after count 1397000 is 2MB

map size: 1398000

Free memory after count 1398000 is 2MB

map size: 1399000

Free memory after count 1399000 is 1MB

map size: 1400000

Free memory after count 1400000 is 1MB

map size: 1401000

Free memory after count 1401000 is 1MB

…..

…..

map size: 1452000

Free memory after count 1452000 is 0MB

map size: 1453000

Free memory after count 1453000 is 0MB

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

 at java.util.HashMap.addEntry(HashMap.java:753)

 at java.util.HashMap.put(HashMap.java:385)

 at MemoryLeak.main(MemoryLeak.java:10)

As you could see, the size of the map keeps growing with the same objects and the available memory keeps coming down from 4MB to 0MB. At the end, the program dies with an OutOfMemoryError.

The death of thread

– Use of system.exit()

– Turning off the power to CPU

– An exception arising in the finally block itself

Rules for catching multiple exceptions

– A more specific catch block must precede a more general one in the source, else it

gives compilation error

– Only one catch block, that is first applicable one, will be executed

Synchronized means only one thread can modify a hash table at one point of time. Any thread before performing an update on a hashtable will have to acquire a lock on the object while others will wait for lock to be released

You should use ArrayList over Vector because you should default to non-synchronized access. Vector synchronizes each individual method. That’s almost never what you want to do. Generally you want to synchronize a whole sequence of operations. Synchronizing individual operations is both less safe (if you iterate over a Vector, for instance, you still need to take out a lock to avoid anyone else changing the collection at the same time) but also slower (why take out a lock repeatedly when once will be enough)? Of course, it also has the overhead of locking even when you don’t need to. It’s a very flawed approach to have synchronized access as default. You can always decorate a collection using Collections.synchronizedList – the fact that Vector combines both the “resized array” collection implementation with the “synchronize every operation” bit is another example of poor design; the decoration approach gives cleaner separation of concerns. Vector also has a few legacy methods around enumeration and element retrieval which are different than the List interface, and developers (especially those who learned Java before 1.2) can tend to use them if they are in the code. Although Enumerations are faster, they don’t check if the collection was modified during iteration, which can cause issues, and given that Vector might be chosen for its syncronization – with the attendant access from multiple threads, this makes it a particularly pernicious problem. Usage of these methods also couples a lot of code to Vector, such that it won’t be easy to replace it with a different List implementation. Despite all above reasons Sun may never officially deprecate Vector class.

At high level – Fail-fast is a property of a system or software with respect to its response to failures. A fail-fast system is designed to immediately report any failure or condition that is likely to lead to failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly-flawed process. When a problem occurs, a fail-fast system fails immediately and visibly. Failing fast is a non-intuitive technique: “failing immediately and visibly” sounds like it would make your software more fragile, but it actually makes it more robust. Bugs are easier to find and fix, so fewer go into production. In Java, Fail-fast term can be related to context of iterators. If an iterator has been created on a collection object and some other thread tries to modify the collection object “structurally”, a concurrent modification exception will be thrown. It is possible for other threads though to invoke “set” method since it doesn’t modify the collection “structurally”. However, if prior to calling “set”, the collection has been modified structurally, “IllegalArgumentException” will be thrown.

It is used to control access of critical code in multithreaded programs

From Sun FAQ Page: Many Collection implementations (including all of the ones provided by the JDK) will have a public clone method, but it would be mistake to require it of all Collections. For example, what does it mean to clone a Collection that’s backed by a terabyte SQL database? Should the method call cause the company to requisition a new disk farm? Similar arguments hold for serializable. If the client doesn’t know the actual type of a Collection, it’s much more flexible and less error prone to have the client decide what type of Collection is desired, create an empty Collection of this type, and use the addAll method to copy the elements of the original collection into the new one. Note on Some Important Terms

  • Synchronized means only one thread can modify a hash table at one point of time. Basically, it means that any thread before performing an update on a hashtable will have to acquire a lock on the object while others will wait for lock to be released.

Fail-fast is relevant from the context of iterators. If an iterator has been created on a collection object and some other thread tries to modify the collection object “structurally”, a concurrent modification exception will be thrown. It is possible for other threads though to invoke “set” method since it doesn’t modify the collection “structurally”. However, if prior to calling “set”, the collection has been modified structurally, “IllegalArgumentException” will be thrown

Vector & ArrayList both classes are implemented using dynamically resizable arrays, providing fast random access and fast traversal. ArrayList and Vector class both implement the List interface.

  • Synchronization – ArrayList is not thread-safe whereas Vector is thread-safe. In Vector class each method like add(), get(int i) is surrounded with a synchronized block and thus making Vector class thread-safe.
  • Data growth – Internally, both the ArrayList and Vector hold onto their contents using an Array. When an element is inserted into an ArrayList or a Vector, the object will need to expand its internal array if it runs out of room. A Vector defaults to doubling the size of its array, while the ArrayList increases its array size by 50 percent.

This can be done by using a simple reflection API hack as demonstrated in below sample code. This example assumes you have a file “c:/Sample.txt” that is not already in class path and at run-time c:/ is added the System classpath and then Sample.txt is made available.

import java.io.File;

import java.io.InputStream;

import java.lang.reflect.Method;

import java.net.URL;

import java.net.URLClassLoader;

 

public class HackJavaClasspath {

 

public static void addURL(URL url) throws Exception {

URLClassLoader cl = (URLClassLoader) ClassLoader

.getSystemClassLoader();

Class clazz = URLClassLoader.class;

 

Method method = clazz.getDeclaredMethod(“addURL”,

new Class[] { URL.class });

method.setAccessible(true);

method.invoke(cl, new Object[] { url });

}

 

public static void main(String[] args) throws Exception {

//Add c: to the classpath

addURL(new File(“c:/”).toURI().toURL());

//Now load the file from new location

InputStream in = Thread.currentThread().getContextClassLoader()

.getResourceAsStream(“Sample.txt”);

System.out.println(in.available());

 

}

}

Running this java class prints the number of bytes available. This indicates the file is available for further processing.

Collections.synchronizedMap(new HashMap());

Collections.synchronizedList(List<T> list)

Deadlock is a situation where two or more threads are blocked forever, waiting for each other. This may occur when two threads, each having a lock on one resource, attempt to acquire a lock on the other’s resource. Each thread would wait indefinitely for the other to release the lock, unless one of the user processes is terminated. In terms of Java API, thread deadlock can occur in following conditions:

  • When two threads call Thread.join() on each other.
  • When two threads use nested synchronized blocks to lock two objects and the blocks lock the same objects in different order.

This can be fixed a number of ways.

Option 1: Method level synchronization. This is the simplest. As you can see, the increment() method is synchronized, so that the other threads must wait for the thread that already has the lock to execute that method.

import java.util.HashMap;

import java.util.Map;

 

public class Counter {

 

//shared variable or resource

private Integer count = Integer.valueOf(0);

 

private Map<String, Integer> userToNumber = new HashMap<String, Integer>(10);

 

public synchronized void  increment() {

try {

count = count + 1;

Thread.sleep(50);

Thread thread = Thread.currentThread();

userToNumber.put(thread.getName(), count);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

public Integer getCount(String name) {

return userToNumber.get(name);

}

}

Option 2: Even though the Option 1 is simple, it locks the entire method and can adversely impact performance for long running methods as each thread has to execute the entire method one at a time. So, the Option 1 can be improved by providing block level lock. Lock only those operations that are acting on the shared resource and making it non-atomic.

The code below uses an Object, which has its own lock to ensure that two threads cannot execute both the Operation 1 and 2 at the same time because there is only one lock.

import java.util.HashMap;

import java.util.Map;

 

public class Counter {

 

//shared variable or resource

private Integer count = Integer.valueOf(0);

 

private Map<String, Integer> userToNumber = new HashMap<String, Integer>(10);

 

private Object mutex = new Object();   // a lock

 

public void  increment() {

try {

synchronized(mutex) {

count = count + 1;                         //operation 1

Thread.sleep(50);

Thread thread = Thread.currentThread();

userToNumber.put(thread.getName(), count); //operation 2

}

// there could be other operations here that uses the shared resource as read only

 

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

public Integer getCount(String name) {

return userToNumber.get(name);

}

}

Option 3: This is a very trivial, but practical example. The Java 5 introduced locks and locks are better than using just objects for more flexible locking scenarios where Locks can be used in place of synchronized blocks. Locks offer more flexibility than synchronized blocks in that a thread can unlock multiple locks it holds in a different order than the locks were obtained. Here is the code that replaces synchronized with a reentrant lock. Synchronized blocks in Java are reentrant, which means if a Java thread enters a synchronized block of code, and thereby take the lock on the object the block is synchronized on, the thread can enter other Java code blocks synchronized on the same lock object.

For example, here is the demo of reentrant lock.

public class Reentrant{

 

public synchronized method1(){

method2();    //calls another synchronized method on the same object

}

 

public synchronized method2(){

//do something

}

}

Here is the Option 3 example using a ReentrantLock.

import java.util.HashMap;

import java.util.Map;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

public class Counter {

 

// shared variable or resource

private Integer count = Integer.valueOf(0);

 

private Map<String, Integer> userToNumber = new HashMap<String, Integer>(10);

 

private Lock mutex = new ReentrantLock(); // a lock

 

public void increment() {

try {

mutex.lock();

try {

count = count + 1;

Thread.sleep(50);

Thread thread = Thread.currentThread();

userToNumber.put(thread.getName(), count);

} finally {

mutex.unlock(); // finally block is executed even if an

// exception is thrown

}

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

 

}

 

}

 

public Integer getCount(String name) {

return userToNumber.get(name);

}

 

}

Note that the locks are unlocked in a finally block as it is executed even if an exception is thrown.

The output for the above 3 options will be something like shown below. The order cannot be guaranteed.

But you will get unique numbers assigned for each user.

User-1 value is 1

User-3 value is 2

User-2 value is 3

Below are some key points about ThreadLocal variables

  • A thread-local variable effectively provides a separate copy of its value for each thread that uses it.
  • ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
  • In case when multiple threads access a ThreadLocal instance, separate copy of Threadlocal variable is maintained for each thread.
  • Common use is seen in DAO pattern where the DAO class can be singleton but the Database connection can be maintained separately for each thread. (Per Thread Singleton)
  • ThreadLocal variable are difficult to understand and I have found below reference links very useful in getting better understanding on them
  • “http://www-128.ibm.com/developerworks/java/library/j-threads3.html”Good article on ThreadLocal on IBM DeveloperWorks
  • “http://javaboutique.internet.com/tutorials/localdata”Managing data : Good example
  • href=”http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html”Refer Java API Docs

The Runnable interface is preferred, as it does not require your object to inherit a thread because when you need multiple inheritance, only interfaces can help you. In the above example we had to extend the Base class so implementing Runnable interface is an obvious choice.

Also note how the threads are started in each of the different cases as shown inthe code sample. In an OO approach you should only extend a class when you want to make it different from it’s superclass, and change it’s behavior.

By implementing a Runnable interface instead of extending the Thread class, you are telling to the user that the class Counter is an object of type Base and will run as a thread.

Get the following exception:

Exception in thread “main” java.lang.IllegalThreadStateException

at java.lang.Thread.start(Thread.java:595)

at deadlock.DeadlockTest.main(DeadlockTest.java:38)

If an application has thread leak then with time it will have too many unused threads. Try to find out what type of threads is leaking out.

This can be done using following ways:

  • Give unique and descriptive names to the threads created in application. – Add log entry in all thread at various entry and exit points in threads.
  • Change debugging config levels (debug, info, error etc) and analyze log messages.
  • When you find the class that is leaking out threads check how new threads are instantiated and how they’re closed.
  • Make sure the thread is Guaranteed to close properly by doing following – Handling all Exceptions properly.
  • Make sure the thread is Guaranteed to close properly by doing following
  • Handling all Exceptions properly.
  • releasing all resources (e.g. connections, files etc) before it closes.

The state chart diagram below describes the thread states.

 

Runnable: A thread becomes runnable when you call the start( ), but does  not necessarily start running immediately.  It will be pooled waiting for its turn to be picked for execution by the thread scheduler based on thread priorities.

MyThread aThread = new MyThread();

aThread.start();                   //becomes runnable

Running: The processor is actively executing the thread code. It runs until it becomes blocked, or voluntarily gives up its turn with this static method Thread.yield( ). Because of context switching overhead, yield( ) should not be used very frequently

Waiting: A thread is in a blocked state while it waits for some external processing such as file I/O to finish.A call to currObject.wait( ) method causes the current thread to wait until some other thread invokescurrObject.notify( ) or the currObject.notifyAll( ) is executed.

Sleeping: Java threads are forcibly put to sleep (suspended) with this overloaded method: Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);

Blocked on I/O: Will move to runnable after I/O condition like reading bytes of data etc changes.

Blocked on synchronization: will move to running when a lock is acquired.

Dead: The thread is finished working.

Thread.State enumeration contains the possible states of a Java thread in the underlying JVM. These thread states are possible due to Java’s following thread concepts:

  • The objects can be shared and modified (i.e. if mutable) by any threads.
  • The preemptive nature of the thread scheduler can swap threads on and off cores in a multi-core CPU machine at any time.
  • This means the methods can be swapped out while they are running. Otherwise a method in an infinite loop will clog the CPU forever leaving the other methods on different threads to starve.
  • To prevent thread safety issues, the methods and block of code that has vulnerable data can be locked.
  • This enables the threads to be in locked or waiting to acquire a lock states.
  • The threads also get into the waiting state for I/O resources like sockets, file handles, and database connections.
  • The threads that are performing I/O read/write operations can not be swapped. Hence, they need to eithercomplete to the finished state with success/failure or another thread must close the socket for it to get to the state of dead or finished. This is why proper service timeout values are necessary to prevent the thread to get blocked for ever in an I/O operation, causing performance issues.
  • The threads can be put to sleep to give other threads in waiting state an opportunity to execute.

A thread pool is a collection of threads on which task can be scheduled. Instead of creating a new thread for each task, you can have one of the threads from the thread pool pulled out of the pool and assigned to the task. When the thread is finished with the task, it adds itself back to the pool and waits for another assignment. One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Below are key reasons to use a Thread Pool

  • Using thread pools minimizes the JVM overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and de-allocating many thread objects creates a significant memory management overhead.
  • You have control over the maximum number of tasks that are being processed in parallel (= number of threads in the pool).

Most of the executor implementations in java.util.concurrent use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks.

The following code snippet changes the Counter class to maintain individual counting as in each user counter will be incremented starting from 1. So, the Counter will no longer be the shared resource. The CountingTask class is also modified to loop through each user 2 times as shown below. Is there anything wrong with the code shown below

The Counter class with individual counts

import java.util.HashMap;

import java.util.Map;

 

public class Counter {

 

 private Map<String, Integer> userToNumber = new HashMap<String, Integer>(10);

 

 public void increment() {

  Thread thread = Thread.currentThread();

  if (!userToNumber.containsKey(thread.getName())) {

   userToNumber.put(thread.getName(), Integer.valueOf(1));  //op1

  } else {

   Integer count = userToNumber.get(thread.getName());

   if (count != null) {

    ++count; // op2: increment it

    userToNumber.put(thread.getName(), count); //op3

   }

  }

}

 

 public Integer getCount(String name) {

  return userToNumber.get(name);

 }

}

 

// The counting task that repeats twice for each user

public class CountingTask implements Runnable {

 

 private Counter counter;

 

 public CountingTask(Counter counter) {

  super();

  this.counter = counter;

 }

 

public void run() {

 

  for (int i = 0; i < 2; i++) {

   counter.increment();

   Thread thread = Thread.currentThread();

   System.out.println(thread.getName() + ” value is “

     + counter.getCount(thread.getName()));

  }

 }

}

If each user will be accessed by only one thread, then the above code is thread-safe because each user will be operating on his/her data.

So, only one thread will access the map entry for User-1, and so on.

But, what happens if User-3 has two threads created as shown below.

The Thread 3 and 4 are User 3.

In this scenario, the above code is not thread safe, and it needs to be made atomic with one of the three options discussed above. It can be quite dangerous to assume that one user will be accessed only by one thread.What if in the future, additional threads are added to improve performance per user?

public class CountingManager

{

public static void main(String[] args) throws InterruptedException

{

 

Counter counter = new Counter(); // create an instance of the Counter

CountingTask task = new CountingTask(counter); // pass the counter to the runnable CountingTask

 

//Create 10 user threads (non-daemon) from the main thread that share the counter object

Thread thread1 = new Thread(task, “User-1”);

Thread thread2 = new Thread(task, “User-2”);

Thread thread3 = new Thread(task, “User-3”); //user 3

Thread thread4 = new Thread(task, “User-3”); //User 3

 

//start the threads

thread1.start();

thread2.start();

thread3.start();

thread4.start();

 

//observe the racing conditions in the output

}

}

If you don’t perform the operations 1 to 3 atomically (i.e. as a unit),

you will get an out put like:

User-1 value is 1

User-1 value is 2

User-3 value is 2

User-3 value is 3

User-3 value is 2

User-3 value is 4

User-2 value is 1

User-2 value is 2

As you can see, the User-3 has the value 2 repeated twice and value 1 is missing. If you apply the one of the options outlined above, you will get an output like:

User-1 value is 1

User-1 value is 2

User-3 value is 1

User-3 value is 2

User-2 value is 1

User-2 value is 2

User-3 value is 3

User-3 value is 4

Hence, the operations 1-3 need to be made atomic if accessed concurrently by multiple threads.Those three operations are

  • storing the initial value
  • incrementing the counter
  • storing the incremented value

In Java, you can use wait(  ) and notifyAll(  ) to communicate between threads. The code below demonstrates that:

 

Note: This a typical example of splitting tasks among threads. A method calls notify/notifyAll( ) as the last thing it does (besides return). Since the printOdd( ) and printEven( ) methods were void, the notifyAll( ) was the last statement. If it were to return some value, the notifyAll( ) would have been placed just before the return statement.

Firstly, create the thread classes and the main method that creates the thread and run it.

package multithreading;

 

public class NumberGenerator extends Thread {

 

private NumberUtility numberUtility;

private int maxNumber;

private boolean isEvenNumber;

 

 

public NumberGenerator(NumberUtility numberUtility, int maxNumber, boolean isEvenNumber) {

this.numberUtility = numberUtility;

this.maxNumber = maxNumber;

this.isEvenNumber = isEvenNumber;

}

 

public void run() {

int i = isEvenNumber == true ? 2 : 1;

while (i <= maxNumber) {

if(isEvenNumber == true) {

numberUtility.printEven(i);

}

else {

numberUtility.printOdd(i);

}

 

i = i + 2;

}

}

 

 

public static void main(String[] args) {

NumberUtility numUtility = new NumberUtility(); //<span id=”IL_AD6″ class=”IL_AD”>single</span> instance shared by oddGen and evenGen threads

final int MAX_NUM = 10;

 

//create 2 threads, one to generate odd numbers and the other to generate even numbers

NumberGenerator oddGen = new NumberGenerator(numUtility, MAX_NUM, false);

NumberGenerator evenGen = new NumberGenerator(numUtility, MAX_NUM, true);

 

oddGen.start();  //start the thread – invokes the run() method on NumberGenerator

evenGen.start(); //start the thread – invokes the run() method on NumberGenerator

 

}

 

}

Next, create the utility class that is used for communicating between the two threads with wait() and notifyAll() methods via synchronized methods.

 

package multithreading;

 

import static java.lang.System.out;

 

public class NumberUtility {

 

boolean oddPrinted = false;

 

public synchronized void printOdd(int number) {

 

while (oddPrinted == true) {

try {

wait();   // waits until notified by even thread

 

} catch (InterruptedException e) {

e.printStackTrace();

}

}

 

out.println(“printOdd() ” + number);

oddPrinted = true;

notifyAll();  //notify all waiting threads

 

}

 

public synchronized void printEven(int number) {

while (oddPrinted == false) {

try {

wait();  //waits until notified by the odd thread

 

} catch (InterruptedException e) {

 

}

}

 

oddPrinted = false;

out.println(“printEven() ” + number);

notifyAll();  //notify all waiting threads

}

}

The output will be something like:

printOdd() 1

printEven() 2

printOdd() 3

printEven() 4

printOdd() 5

printEven() 6

printOdd() 7

printEven() 8

printOdd() 9

printEven() 10

Starvation and livelock are much less common a problem than deadlock, but are still problems that every designer of concurrent software is likely to encounter.

LiveLock

Livelock occurs when all threads are blocked, or are otherwise unable to proceed due to unavailability of required resources, and the non-existence of any unblocked thread to make those resources available. In terms of Java API, thread livelock can occur in following conditions:

  • When all the threads in a program execute Object.wait(0) on an object with zero parameter. The program is live-locked and cannot proceed until one or more threads call Object.notify() or Object.notifyAll() on the relevant objects. Because all the threads are blocked, neither call can be made.
  • When all the threads in a program are stuck in infinite loops.

Starvation

Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by “greedy” threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked. Starvation occurs when one thread cannot access the CPU because one or more other threads are monopolizing the CPU. In Java, thread starvation can be caused by setting thread priorities inappropriately. A lower-priority thread can be starved by higher-priority threads if the higher-priority threads do not yield control of the CPU from time to time.

Thread.sleep() takes the current thread to a “Not Runnable” state for specified amount of time. The thread holds the monitors it has acquired. For example, if a thread is running a synchronized block or method and sleep method is called then no other thread will be able to enter this block or method. The sleeping thread can wake up when some other thread calls t.interrupt on it. Note that sleep is a static method, that means it always affects the current thread (the one executing sleep method). A common mistake is trying to call t2.sleep() where t2 is a different thread; even then, it is the current thread that will sleep, not the t2 thread. thread.suspend() is deprecated method. Its possible to send other threads into suspended state by making a suspend method call. In suspended state a thread keeps all its monitors and can not be interrupted. This may cause deadlocks therefore it has been deprecated. object.wait() call also takes the current thread into a “Not Runnable” state, just like sleep(), but with a slight change. Wait method is invoked on a lock object, not thread.

Here is the sequence of operations you can think:

  • A thread T1 is already running a synchronized block with a lock on object – lets say “lockObject”
  • Another thread T2 comes to execute the synchronized block and find that its already acquired.
  • Now T2 calls lockObject.wait() method for waiting on lock to be release by T1 thread.
  • T1 thread finishes all its synchronized block work.
  • T1 thread calls lockObject.notifyAll() to notify all waiting threads that its done using the lock.
  • Since T2 thread is first in the queue of waiting it acquires the lock and starts processing.

When a task invokes yield( ), it changes from running state to runnable state.

When a task invokes sleep ( ), it changes from running state to waiting/sleeping state.

The method wait(1000), causes the current thread to sleep up to one second. A thread could sleep less than 1 second if it receives the notify( ) or notifyAll( ) method call.

The call to sleep(1000) causes the current thread to sleep for 1 second.

Yes, the run method of a runnable class can be synchronized. If you make run method synchronized then the lock on runnable object will be occupied before executing the run method. In case we start multiple threads using the same runnable object in the constructor of the Thread then it would work. But until the 1st thread ends the 2nd thread cannot start and until the 2nd thread ends the next cannot start as all the threads depend on lock on same object.

With respect to multi-threading, synchronization is the capability to control the access of multiple threads to shared resources. Without synchronization, it is possible for one Java thread to modify a shared variable while another thread is in the process of using or updating same shared variable. This usually leads to erroneous behavior or program.

Earlier versions of Java had no mechanism to handle/detect deadlock. Since JDK 1.5 there are some powerful methods added in the java.lang.management package to diagnose and detect deadlocks. The java.lang.management.ThreadMXBean interface is management interface for the thread system of the Java virtual machine. It has two methods which can leveraged to detect deadlock in a Java application.

  • findMonitorDeadlockedThreads() – This method can be used to detect cycles of threads that are in deadlock waiting to acquire object monitors. It returns an array of thread IDs that are deadlocked waiting on monitor.
  • findDeadlockedThreads() – It returns an array of thread IDs that are deadlocked waiting on monitor or ownable synchronizers.

In Unix, a pipe (“|”) operator helps you to redirect output from one command to another.

PipedReader and PipedWriterclasses in java.io package helps you to do the same.

It helps you to redirect the read input into writer seamlessly.

In Unix, two different processes on different address spaces can communicate using pipe, but in java two threads on the JVM can communicate using Piped ByteStream/CharacterStream within the same process

(i.e same address space)

 

 

 

Here is the code snippet. The Writer threads responsible for writing odd and even numbers to the respective pipes.

package multithreading;

 

import java.io.IOException;

import java.io.PipedWriter;

 

public class NumberWriter extends Thread {

 

private PipedWriter writer;

private int maxNumber;

private boolean isEvenNumber;

 

public NumberWriter(PipedWriter writer, int maxNumber, boolean isEvenNumber) {

this.writer = writer;

this.maxNumber = maxNumber;

this.isEvenNumber = isEvenNumber;

}

 

public void run() {

int i = 1;

while (i <= maxNumber) {

try {

if (isEvenNumber && (i % 2) == 0) {

writer.write(i);

} else if (!isEvenNumber && i%2 != 0) {

writer.write(i);

}

++i;

} catch (IOException e) {

e.printStackTrace();

}

}

}

 

public static void main(String[] args) {

final int MAX_NUM = 10;

 

PipedWriter oddNumberWriter = new PipedWriter();

PipedWriter evenNumberWriter = new PipedWriter();

 

NumberWriter oddGen = new NumberWriter(oddNumberWriter, MAX_NUM, false);

NumberWriter evenGen = new NumberWriter(evenNumberWriter, MAX_NUM, true);

NumberReceiver receiver = new NumberReceiver(oddNumberWriter, evenNumberWriter);

 

oddGen.start();

evenGen.start();

receiver.start();

 

}

 

}

 

 

The receiver thread that listens to both odd and even number pipes and computes the sum. If the sum is a multiple of 5, it prints the numbers and the sum.

package multithreading;

 

import java.io.IOException;

import java.io.PipedReader;

import java.io.PipedWriter;

 

public class NumberReceiver extends Thread {

 

private PipedReader oddReader;

private PipedReader evenReader;

 

public NumberReceiver(PipedWriter oddWriter, PipedWriter evenWriter) {

try {

this.oddReader = new PipedReader(oddWriter);

this.evenReader = new PipedReader(evenWriter);

} catch (IOException e) {

e.printStackTrace();

}

}

 

public void run() {

int odd =0, even=0;

 

try {

while (odd != -1) {

odd = oddReader.read();

even = evenReader.read();

 

if ((odd + even) % 5 == 0) {

System.out.println(“match found ” + odd + ” + ” + even + ” = ” + (odd + even));

}

}

 

} catch (IOException e) {

System.exit(1);

}

 

 

}

}

The output will be something like:

match found 7 + 8 = 15

As per Java Language Specification, constructors cannot be synchronized because other threads cannot see the object being created before the thread creating it has finished it. There is no practical need of a Java Objects constructor to be synchronized, since it would lock the object being constructed, which is normally not available to other threads until all constructors of the object finish

An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code. Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state. Examples of immutable objects from the JDK include String and Integer. Immutable objects greatly simplify your multi threaded program, since they are

  • Simple to construct, test, and use.
  • Automatically thread-safe and have no synchronization issues.

To create a object immutable You need to make the class final and all its member final so that once objects gets crated no one can modify its state. You can achieve same functionality by making member as non final but private and not modifying them except in constructor.

Synchronized static methods have a lock on the class “Class”, so when a thread enters a synchronized static method, the class itself gets locked by the thread monitor and no other thread can enter any static synchronized methods on that class. This is unlike instance methods, as multiple threads can access “same synchronized instance methods” at same time for different instances.

  • Declaring variables in JSP pages are not thread-safe. The declared variables in JSP pages end-up as instance variables in the converted Servlets. <%! Calendar c = Calendar.getInstance(); %>
  • Decalring instance variables in Servlets is not thread safe, as Servlets are inherently multi-threaded and gets accessed by multiple-threads. Same is true for the Actionclasses in the struts framework.
  • Some of the Java standard library classes likeSimpleDateFormat is not thread-safe. Always check the API to see if a particular class is thread-safe. If a particular class or library is not therad-safe, you could do one of three things.

Provide your own wrapper class that decorates the third-party library with proper synchronization.

This is a typical use of the decorator design pattern.

Use an alternative library, which is thread-safe if available.

For example, Joda Time Library.

Use it in a thread-safe manner.

For example, you could use the SimpleDateFormat class as shown below within a ThreadLocal class.

Each thread will have its own instance of the SimpleDateFormat object.

 

public class DateFormatTest

{

//          anonymous inner class. Each thread will have its own copy

 

private final static ThreadLocal<SimpleDateFormat> shortDateFormat

=  new ThreadLocal<SimpleDateFormat>()

{

protected SimpleDateFormat initialValue()

{

return new SimpleDateFormat(“dd/MM/yyyy”);

}

};

 

public Date convert(String strDate)throws ParseException

{

//          get the SimpleDateFormat instance for this thread and parse the date string

 

Date d = shortDateFormat.get().parse(strDate);

return d;

}

}

  • The one that is very popular with the interviewers is writing the singleton classes that are not thread-safe.

When a method or block of code is locked with the reserved “synchronized” key word in Java, the memory (i.e. heap) where the shared data is kept is synchronized.

This means,When a synchronized block or method is entered after the lock has been acquired by a thread, it first reads any changes to the locked object from the main heap memory to ensure that the thread that has the lock has the current info before start executing.

After the synchronized  block has completed and the thread is ready to relinquish the lock, all the changes that were made to the object that was locked is written or flushed back to the main heap memory so that the other threads that acquire the lock next has the current info.

This is why it is called “synchronized” and not “locked”. This is also the reason why the immutable objects are inherently thread-safe and does not require any synchronization. Once created, the immutable objects cannot be modified.

A Java thread could be implemented by using Runnable interface or by extending the Thread class. The Runnable is more advantageous, when you are going for multiple inheritance.

A process is an execution of a program but a thread is a single execution sequence within the process. A process can contain multiple threads. A thread is sometimes called a lightweight process.

 

A JVM runs in a single process and threads in a JVM share the heap belonging to that process. That is why several threads may access the same object. Threads share the heap and have their own stack space. This is how one thread’s invocation of a method and its local variables are kept thread safe from other threads. But the heap is not thread-safe and must be synchronized for thread safety.

A Thread Dump is a complete list of active threads. A java thread dump is a way of finding out what each thread in the JVM is doing at a particular point of time. This is especially useful when your java application seems to have some performance issues. Thread dump will help you to find out which thread is causing this. There are several ways to take thread dumps from a JVM. It is highly recommended to take more than 1 thread dump and analyze the results based on it. Follow below steps to take thread dump of a java process

  • Step 1

On UNIX, Linux and Mac OSX Environment run below command:

ps -el | grep java

On Windows:

Press Ctrl+Shift+Esc to open the task manager and find the PID of the java

process

  • Step 2:

Use jstack command to print the Java stack traces for a given Java process PID

jstack [PID]

Yes, a Non synchronized method can always be called without any problem. In fact Java does not do any check for a non-synchronized method. The Lock object check is performed only for synchronized methods/blocks. In case the method is not declared synchronized Jave will call even if you are playing with shared data. So you have to be careful while doing such thing. The decision of declaring a method as synchronized has to be based on critical section access. If your method does not access a critical section (shared resource or data structure) it need not be declared synchronized. Below is the example which demonstrates this, The Common class has two methods synchronizedMethod1() and method1() MyThread class is calling both the methods in separate threads,

public class Common {

public synchronized void synchronizedMethod1() {

System.out.println(“synchronizedMethod1 called”);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“synchronizedMethod1 done”);

}

public void method1() {

System.out.println(“Method 1 called”);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“Method 1 done”);

}

}

public class MyThread extends Thread {

private int id = 0;

private Common common;

public MyThread(String name, int no, Common object) {

super(name);

common = object;

id = no;

}

public void run() {

System.out.println(“Running Thread” + this.getName());

try {

if (id == 0) {

common.synchronizedMethod1();

} else {

common.method1();

}

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Common c = new Common();

MyThread t1 = new MyThread(“MyThread-1”, 0, c);

MyThread t2 = new MyThread(“MyThread-2”, 1, c);

t1.start();

t2.start();

}

}  

Here is the output of the program

Running ThreadMyThread-1

synchronizedMethod1 called

Running ThreadMyThread-2

Method 1 called

synchronizedMethod1 done

Method 1 done

This shows that method1() – is called even though the synchronizedMethod1() was in execution.

Thread.start() method (native method) of Thread class actually does the job of running the Thread.run() method in a thread. If we directly call Thread.run() method it will executed in same thread, so does not solve the purpose of creating a new thread.

A singleton class is something for which only one instance exists per class loader. Single instance for a wholeapplication cannot be guaranteed. That is just definition of what is singleton.

The one that is  popular with the interviewers is writing a thread-safe singleton class.

For example, the following singleton class is not thread-safe because before a thread creates the Singleton instance, another thread can proceed to the instantiation part of the code

— instance = new Object( );

to create more than one instance of the Singleton object.

Even though the code

–> instance = new Object( );

appears to be single line, the JVM has to execute a number of internal steps like allocating memory, creating a new object and assigning the newly created object to the referenced variable.

Only after the completion of these steps,the condition instance == null will return false.

//          final so that cannot be subclassed

public final class Singleton {

 

private static Object instance = null;

 

//private so that it cannot be instantiated from outside this class

private Singleton() {}

 

public static Object getInstance() {

if (instance == null) {

instance = new Object();

}

 

return instance;

}

}

So, we can make the above code thread-safe in a number of ways.

Option 1: Synchronize the whole method or the block of code. This approach is not efficient as the use of synchronized keyword in a singleton class means that only one thread will be executing the synchronized block at a time and all other threads would be waiting.

Option 2: Eagerly initialize the singleton instance when the class is actually loaded as opposed to initializing it lazily at at run time only when it is accessed.

//final so that cannot be subclassed

public final class ThreadSafeSingleton {

 

//eager initialization and instantitiated as soon as the class is loaded by a classloader in the JVM

private static Object instance = new Object();

 

//private so that it cannot be instantiated from outside this class

private Singleton() {}

 

public static Object getInstance() {

return instance;

}

}

Option 3: You can use the “Initialize-On-Demand Holder Class” idiom proposed by Brian Goetz to create a thread-safe lazy-initialized Singleton as shown below by creating an inner class.

public final class ThreadSafeSingleton {

//      private so that it cannot be instantiated from outside this class

private ThreadSafeSingleton() {}

 

//      static inner class, invoked only when ThreadSafeSingleton.getInstance() is called

private static class ThreadSafeSingletonHolder {

private static ThreadSafeSingleton instance = new ThreadSafeSingleton();

}

public static Object getInstance() {

return ThreadSafeSingletonHolder.instance;

}

}

Option 4: is to create a per thread singleton as discussed earlier with the ThreadLocal class for the SimpledateFormat.

  • In Java programming, each object has a lock. A thread can acquire the lock for an object by using the synchronized keyword.
  • The synchronized keyword can be applied in method level (coarse grained lock – can affect performance adversely) or block level of code (fine grained lock).
  • Often using a lock on a method level is too coarse. Why lock up a piece of code that does not access any shared resources by locking up an entire method.
  • Since each object has a lock, dummy objects can be created to implement block level synchronization.
  • The block level is more efficient because it does not lock the whole method.
  • The JVM uses locks in conjunction with monitors.
  • A monitor is basically a guardian who watches over a sequence of synchronized code and making sure only one thread at a time executes a synchronized piece of code.
  • Each monitor is associated with an object reference.
  • When a thread arrives at the first instruction in a block of code it must obtain a lock on the referenced object.
  • The thread is not allowed to execute the code until it obtains the lock.
  • Once it has obtained the lock, the thread enters the block of protected code.

 

  • When the thread leaves the block, no matter how it leaves the block, it releases the lock on the associated object. For static methods, you acquire a class level lock.

The example below causesa deadlocksituation bythread-1 waiting for lock2and thread-0 waiting for lock1.

 

package deadlock;

 

public class DeadlockTest extends Thread

{

public static Object lock1 = new Object();

public static Object lock2 = new Object();

public void method1()

{

synchronized (lock1)

{

delay(500);  //some operation

System.out.println(“method1: ” + Thread.currentThread().getName());

synchronized (lock2)

{

System.out.println(“method1 is executing …. “);

}

}

}

public void method2()

{

synchronized (lock2)

{

delay(500);   //some operation

System.out.println(“method1: ” + Thread.currentThread().getName());

synchronized (lock1)

{

System.out.println(“method2 is executing …. “);

}

}

}

public void run()

{

method1();

method2();

}

public static void main(String[] args)

{

DeadlockTest thread1 = new DeadlockTest();

DeadlockTest thread2 = new DeadlockTest();

 

thread1.start();

thread2.start();

}

private</span> void delay(long timeInMillis)

{

try

{

Thread.sleep(timeInMillis);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

}

The output will be something like:

method1: Thread-0

method1 is executing ….

method2: Thread-0

method1: Thread-1

—deadlock —– can’t proceed further

We need run() & start() method both because JVM needs to create a separate thread which can not be differentiated from a normal method call. So this job is done by start method native implementation which has to be explicitly called. Another advantage of having these two methods is we can have any object run as a thread if it implements Runnable interface. This is to avoid Java’s multiple inheritance problems which will make it difficult to inherit another class with Thread.

Threads can be used by either:

  • Extending the Thread class.
  • Implementing the Runnable interface.

Using the Executor framework (this creates a thread pool)

 

By extends:

class Counter extends Thread {

 

//method where the thread execution will start

public void run(){

//logic to execute in a thread

}

 

//let’s see how to start the threads

public static void main(String[] args){

Thread t1 = new Counter();

Thread t2 = new Counter();

t1.start();  //start the first thread. This calls the run() method.

t2.start(); //this starts the 2nd thread. This calls the run() method.

}

}

By implements:

class Counter extends Base implements Runnable{

 

//method where the thread execution will start

public void run(){

//logic to execute in a thread

}

 

//let us see how to start the threads

public static void main(String[] args){

Thread t1 = new Thread(new Counter());

Thread t2 = new Thread(new Counter());

t1.start();  //start the first thread. This calls the run() method.

t2.start();  //this starts the 2nd thread. This calls the run() method.

}

}

The thread pool is more efficient and  learn why and how to create pool of  threads using the executor framework.

Thread leak is when a application does not release references to a thread object properly. Due to this some Threads do not get garbage collected and the number of unused threads grow with time. Thread leak can often cause serious issues on a Java application since over a period of time too many threads will be created but not released and may cause applications to respond slow or hang.

No. If a object has synchronized instance methods then the Object itself is used a lock object for controlling the synchronization. Therefore all other instance methods need to wait until previous method call is completed. See the below sample code which demonstrate it very clearly. The Class Common has 2 methods called synchronizedMethod1() and synchronizedMethod2() MyThread class is calling both the methods

public class Common {

public synchronized void synchronizedMethod1() {

System.out.println(“synchronizedMethod1 called”);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“synchronizedMethod1 done”);

}

public synchronized void synchronizedMethod2() {

System.out.println(“synchronizedMethod2 called”);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“synchronizedMethod2 done”);

}

}

public class MyThread extends Thread {

private int id = 0;

private Common common;

 

public MyThread(String name, int no, Common object) {

super(name);

common = object;

id = no;

}

public void run() {

System.out.println(“Running Thread” + this.getName());

try {

if (id == 0) {

common.synchronizedMethod1();

} else {

common.synchronizedMethod2();

}

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Common c = new Common();

MyThread t1 = new MyThread(“MyThread-1”, 0, c);

MyThread t2 = new MyThread(“MyThread-2”, 1, c);

t1.start();

t2.start();

}

}

The code snippets below demonstrates non-atomic operations producing incorrect results with code. The program below uses a shared Counter object, that is shared between three concurrent users (i.e. three threads). The Counter object is responsible for incrementing the counter.

Firstly, the Counter class. The counted values are stored in a HashMap by name (i.e. thread name) as the key for later retrieval.

import java.util.HashMap;

import java.util.Map;

 

public class Counter {

 

//         shared variable or resource

private Integer count = Integer.valueOf(0);

private Map<String, Integer> userToNumber = new HashMap<String, Integer>(10);

 

public void  increment() {

try {

count = count + 1;      //          increment the counter

Thread.sleep(50);      //          to imitate other operations and

//          to make the racing condion to occur more often for the demo

Thread thread = Thread.currentThread();

userToNumber.put(thread.getName(), count);

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

public Integer getCount(String name) {

return userToNumber.get(name);

}

}

Next, the Runnable task where each thread will be entering and executing concurrently.

public class CountingTask implements Runnable

{

private Counter counter;

public CountingTask(Counter counter) {

super();

this.counter = counter;

}

 

public void run() {

counter.increment();

Thread thread = Thread.currentThread();

System.out.println(thread.getName() + ” value is ” + counter.getCount(thread.getName()));

}

}

Finally, the Manager class that creates 3 new threads from the main thread.

public class CountingManager {

 

public static void main(String[] args) throws InterruptedException

{

 

Counter counter = new Counter(); // create an instance of the Counter

CountingTask task = new CountingTask(counter); // pass the counter to the runnable CountingTask

 

//Create 10 user threads (non-daemon) from the main thread that share the counter object

Thread thread1 = new Thread(task, “User-1”);

Thread thread2 = new Thread(task, “User-2”);

Thread thread3 = new Thread(task, “User-3”);

 

//start the threads

thread1.start();

thread2.start();

thread3.start();

 

//observe the racing conditions in the output

}

}

To see the racing condition, inspect the output of the above code:

User-3 value is 3

User-1 value is 3

User-2 value is 3

All three threads or users get assigned the same value of 3 due to racing conditions. We are expecting to see three different count values to be assigned from 1 to 3. What happened here is that when the first thread incremented the count from 0 to 1 and entered into the sleep(50) block, the second and third threads incremented the counts from 1 to 2 and 2 to 3 respectively.

This shows that the 2 operations — the operation that increments the thread and the operation that stores the incremented value in a HashMap are not atomic, and produces incorrect results due to racing conditions.