50+ Java Interview Questions for Programmers

Hello, guys! Recently, I have been sharing a lot of Java Interview questions and discussion individually, and many of my readers requested to bring them together so that they can have them in the same page and prepare better and this post is the result of that.

This article contains more than 50 Java Interview questions covering all important topics like core Java fundamentals, Java Collection FrameworkJava Multithreading and ConcurrencyJava IOJDBCJVM InternalsCoding ProblemsObject-Oriented programming, etc.

The questions are also picked up from various interviews and they are, by no means, very difficult, and you might have seen them already in your telephonic or face-to-face round of interview.

The questions are also very good to revise important topics like multithreading and collections as I have also shared some useful resources for further learning and improvement like The Complete Java MasterClass to brush up and fill gaps in your Java skills.

So what are we waiting for here is the list of some of the frequently asked Java questions from interviews from both beginner and experienced Java developer of 2 to 5 years experience:

Java Interview Questions and Answers

1)  How Java achieves platform independence? (answer)
hint: bytecode and Java Virtual Machine

2)  What is ClassLoader in Java? (answer)
hint: part of JVM that loads bytecodes for classes. You can write your own.

3)  Write a Java program to check if a number is Even or Odd? (answer)
hint: you can use bitwise operator, e.g. bitwise AND &, remember, even the number has zero at the end in binary format and an odd number has 1 in the end.

4)  Difference between ArrayList and HashSet in Java? (answer)
hint: all differences between List and Set are applicable here, e.g. ordering, duplicates, random search, etc.

5)  What is double checked locking in Singleton? (answer)
hint: two-time check whether instances is initialized or not, first without locking and second with locking.

6)  How do you create thread-safe Singleton in Java? (answer)
hint: many ways, e.g. using Enum or by using double-checked locking pattern or using a nested static class.

7)  When to use volatile variable in Java? (answer)
hint: when you need to instruct the JVM that a variable can be modified by multiple threads and give hint to JVM that does not cache its value.

8)  When to use a transient variable in Java? (answer)
hint: when you want to make a variable non-serializable in a class, which implements the Serializable interface. In other words, you can use it for a variable whose value you don’t want to save. See The Complete Java MasterClass to learn about transient variables in Java.

9)  Difference between the transient and volatile variable in Java? (answer)
hint: totally different, one used in the context of serialization while the other is used in concurrency.

10) Difference between Serializable and Externalizable in Java? (answer)
hint: Externalizable gives you more control over the Serialization process.

11) Can we override the private method in Java? (answer)
hint: No, because it’s not visible in the subclass, a primary requirement for overriding a method in Java.

12) Difference between Hashtable and HashMap in Java? (answer)

hint: several but most important is Hashtable, which is synchronized, while HashMap is not. It’s also legacy and slow as compared to HashMap.

13) Difference between Listand Set in Java? (answer)
hint: List is ordered and allows duplicate. Set is unordered and doesn’t allow duplicate elements.

14) Difference between ArrayList and Vector in Java (answer)
hint: Many, but most important is that ArrayList is non-synchronized and fast while Vector is synchronized and slow. It’s also legacy class like Hashtable.

15) Difference between Hashtable and ConcurrentHashMap in Java? (answer)
hint: more scalable

16) How does ConcurrentHashMap achieve scalability? (answer)
hint: by dividing the map into segments and only locking during the write operation.

17) Which two methods you will override for an Object to be used as Key in HashMap? (answer)
hint: equals and hashcode

18) Difference between wait and sleep in Java? (answer)
hint: The wait() method releases the lock or monitor, while sleep doesn’t.

19) Difference between notify and notifyAll in Java? (answer)
hint: notify notifies one random thread is waiting for that lock while notifyAll inform to all threads waiting for a monitor. If you are certain that only one thread is waiting then use notify, or else notifyAll is better. See Threading Essentials Mini-Course by Java Champion Heinz Kabutz to learn more about threading basics.

20) Why you override hashcode, along with equals() in Java? (answer)
hint: to be compliant with equals and hashcode contract, which is required if you are planning to store your object into collection classes, e.g. HashMap or ArrayList.

21) What is the load factor of HashMap means? (answer)
hint: The threshold that triggers the re-sizing of HashMap is generally 0.75, which means HashMap resize itself if it’s 75 percent full.

22) Difference between ArrayList and LinkedList in Java? (answer)
hint: same as an array and linked list, one allows random search while other doesn’t. Insertion and deletion easy on the linked list but a search is easy on an array. See Java Fundamentals: Collections Richard Warburton course on Pluralsight to learn more about essential Collection data structure in Java.

23) Difference between CountDownLatch and CyclicBarrier in Java? (answer)
hint: You can reuse CyclicBarrier after the barrier is broken but you cannot reuse CountDownLatch   after the count reaches to zero.

24) When do you use Runnable vs Thread in Java? (answer)
hint: always

25) What is the meaning of Enum being type-safe in Java? (answer)
hint: It means you cannot assign an instance of different Enum type to an Enum variable. e.g. if you have a variable like DayOfWeek day then you cannot assign it value from DayOfMonth enum.

26) How does Autoboxing of Integer work in Java? (answer)
hint: using valueOf() method

27) Difference between PATH and Classpath in Java? (answer)
hint: PATH is used by the operating system while Classpath is used by JVM to locate Java binary, e.g. JAR files or Class files. See Java Fundamentals: The Core Platform to learn more about PATHClasspath, and other Java environment variable.

28) Difference between method overloading and overriding in Java? (answer)
hint: Overriding happens at subclass while overloading happens in the same class. Also, overriding is a runtime activity while overloading is resolved at compile time.

29) How do you prevent a class from being sub-classed in Java? (answer)
hint: just make its constructor private

30) How do you restrict your class from being used by your client? (answer)
hint:  make the constructor private or throw an exception from the constructor

31) Difference between StringBuilder and StringBuffer in Java? (answer)
hint: StringBuilder is not synchronized while StringBuffer is synchronized.

32) Difference between Polymorphism and Inheritance in Java? (answer)
hint: Inheritance allows code reuse and builds the relationship between class, which is required by Polymorphism, which provides dynamic behavior. See Java Fundamentals: Object-Oriented Design to learn more about OOP features.

33) Can we override static method in Java? (answer)
hint: No, because overriding resolves at runtime while static method call is resolved at compile time.

34) Can we access the private method in Java? (answer)
hint: yes, in the same class but not outside the class

35) Difference between interface and abstract class in Java? (answer)
hint: from Java 8, the difference is blurred. However, a Java class can still implement multiple interfaces but can only extend one class.

36) Difference between DOM and SAX parser in Java? (answer)
hint: DOM loads whole XML File in memory while SAX doesn’t. It is an event-based parser and can be used to parse a large file, but DOM is fast and should be preferred for small files.

37) Difference between throw and throws keyword in Java? (answer)
hint: throws declare what exception a method can throw in case of error but throw keyword actually throws an exception. See Java Fundamentals: Exception Handling to learn more about Exception handling in Java.

38) Difference between fail-safe and fail-fast iterators in Java? (answer)
hint: fail-safe doesn’t throw ConcurrentModificationException while fail-fast does whenever they detect an outside change on the underlying collection while iterating over it.

39) Difference between Iterator and Enumeration in Java? (answer)
hint: Iterator also gives you the ability to remove an element while iterating while Enumeration doesn’t allow that.

40) What is IdentityHashMap in Java? (answer)
hint: A Map, which uses  the == equality operator to check equality instead of the equals() method.

41) What is String pool in Java? (answer)
hint: A pool of String literals. Remember it’s moved to heap from perm gen space in JDK 7.

42) Can a Serializable class contain a non-serializable field in Java? (answer)

hint: Yes, but you need to make it either static or transient.

43) Difference between this and super in Java? (answer)
hint: this refers to the current instance while super refers to an instance of the superclass.

44) Difference between Comparator and Comparable in Java? (answer)
hint: Comparator defines custom ordering while Comparable defines the natural order of objects, e.g. the alphabetic order for String. See The Complete Java MasterClass to learn more about sorting in Java.

45) Difference between java.util.Date and java.sql.Date in Java? (answer)
hint: former contains both date and time while later contains only date part.

46) Why wait and notify method are declared in Object class in Java? (answer)
hint: because they require lock which is only available to an object.

47) Why Java doesn’t support multiple inheritances? (answer)
hint: It doesn’t support because of bad experience with C++, but with Java 8, it does in some sense — only multiple inheritances of Type are not supported in Java now.

48) Difference between checked and unchecked Exception in Java? (answer)
hint: In case of checked, you must handle exception using catch block, while in case of unchecked, it’s up to you; compile will not bother you.

49) Difference between Error and Exception in Java? (answer)
hint: I am tired of typing please check the answer

50) Difference between race condition and deadlock in Java? (answer)
hint: both are errors that occur in a concurrent application, one occurs because of thread scheduling while others occur because of poor coding.

Additional Resources

7 Techniques for thread-safe classes

Almost every Java application uses threads. A web server like Tomcat process each request in a separate worker thread, fat clients process long-running requests in dedicated worker threads, and even batch processes use the java.util.concurrent.ForkJoinPool to improve performance.

It is, therefore, necessary to write classes in a thread-safe way, which can be achieved by one of the following techniques:

No state

When multiple threads access the same instance or static variable you must somehow coordinate the access to this variable. The easiest way to do this is simply by avoiding instance or static variables. Methods in classes without instance variables do only use local variables and method arguments. The following example shows such a method which is part of the class java.lang.Math:

1
2
3
4
5
6
7
public static int subtractExact(int x, int y) {
  int r = x - y;
  if (((x ^ y) & (x ^ r)) < 0) {
      throw new ArithmeticException("integer overflow");
  }
  return r;
}

No shared state

If you can not avoid state do not share the state. The state should only be owned by a single thread. An example of this technique is the event processing thread of the SWT or Swing graphical user interface frameworks.

You can achieve thread-local instance variables by extending the thread class and adding an instance variable. In the following example, the field pool and workQueue are local to a single worker thread.

1
2
3
4
5
package java.util.concurrent;
public class ForkJoinWorkerThread extends Thread {
    final ForkJoinPool pool;               
    final ForkJoinPool.WorkQueue workQueue;
}

The other way to achieve thread-local variables is to use the class java.lang.ThreadLocal for the fields you want to make thread-local. Here is an example of an instance variable using java.lang.ThreadLocal:

1
2
3
4
5
6
7
8
9
10
11
public class CallbackState {
public static final ThreadLocal<CallbackStatePerThread> callbackStatePerThread =
    new ThreadLocal<CallbackStatePerThread>()
   {
      @Override
        protected CallbackStatePerThread  initialValue()
      {
       return getOrCreateCallbackStatePerThread();
      }
   };
}

You wrap the type of your instance variable inside the java.lang.ThreadLocal. You can provide an initial value for your java.lang.ThreadLocal through the method initialValue().

The following shows how to use the instance variable:

1
CallbackStatePerThread callbackStatePerThread = CallbackState.callbackStatePerThread.get();

Through calling the method get() you receive the object associated with the current thread.

Since in application servers a pool of many threads is used to process requests, java.lang.ThreadLocal leads to a high memory consumption in this environment. java.lang.ThreadLocal is therefore not recommended for classes executed by the request processing threads of an application server.

Message passing

If you do not share state using the above techniques you need a way for the threads to communicate. A technique to do this is by passing messages between threads. You can implement message passing using a concurrent queue from the package java.util.concurrent. Or, better yet, use a framework like Akka, a framework for actor style concurrency. The following example shows how to send a message with Akka:

1
target.tell(message, getSelf());

and receive a message:

1
2
3
4
5
6
@Override
public Receive createReceive() {
   return receiveBuilder()
      .match(String.class, s -> System.out.println(s.toLowerCase()))
      .build();
}

Immutable state

To avoid the problem that the sending thread changes the message during the message is read by another thread, messages should be immutable. The Akka framework, therefore, has the convention that all messages have to be immutable

When you implement an immutable class you should declare its fields as final. This not only makes sure that the compiler can check that the fields are in fact immutable but also makes them correctly initialized even when they are incorrect published. Here is an example of a final instance variable:

1
2
3
4
5
6
7
8
public class ExampleFinalField
{
  private final int finalField;
  public ExampleFinalField(int value)
  {
   this.finalField = value;
  }
}

final is a field modifier. It makes the field immutable not the object the field references to. So the type of the final field should be a primitive type like in the example or also an immutable class.

Use the data structures from java.util.concurrent

Message passing uses concurrent queues for the communication between threads. Concurrent Queues are one of the data structures provided in the package java.util.concurrent. This package provides classes for concurrent maps, queues, dequeues, sets and lists. Those data structures are highly optimized and tested for thread safety.

Synchronized blocks

If you can not use one of the above techniques use synchronized locks. By putting a block inside a synchronized block you make sure that only one thread at a time can execute this section.

1
2
3
4
synchronized(lock)
{
 i++;
}

Beware that when you use multiple nested synchronize blocks you risk deadlocks. A deadlock happens when two threads are trying to acquire a lock held by the other thread.

Volatile fields

Normal, nonvolatile fields, can be cached in registers or caches. Through the declaration of a variable as volatile, you tell the JVM and the compiler to always return the latest written value. This not only applies to the variable itself but to all values written by the thread which has written to the volatile field. The following shows an example of a volatile instance variable:

1
2
3
4
public class ExampleVolatileField
{
  private volatile int  volatileField;
}

You can use volatile fields if the writes do not depend on the current value. Or if you can make sure that only one thread at a time can update the field.

volatile is a field modifier. It makes the field itself volatile not the object it references. In case of an array you need to use java.util.concurrent.atomic.AtomicReferenceArray to access the array elements in a volatile way. See the race condition in org.­springframework.­util.­ConcurrentReferenceHashMap as an example of this error.

Even more techniques

I excluded the following more advanced techniques from this list: Atomic updates, a technique in which you call atomic instructions like compare and set provided by the CPU, java.util.concurrent.locks.ReentrantLock, a lock implementation which provides more flexibility than synchronized blocks, java.util.concurrent.locks.ReentrantReadWriteLock, a lock implementation in which reads do not block reads and java.util.concurrent.locks.StampedLock a nonreeantrant Read-Write lock with the possibility to optimistically read values.

Conclusion

The best way to achieve thread safety is to avoid shared state. For the state, you need to share you can either use message parsing together with immutable classes or the concurrent data structures together with synchronized blocks and volatile fields.

I would be glad to hear from you about the techniques you use to achieve thread-safe classes.

How To Stop A Thread In Java?

How do you stop a thread in java? now-a-days, this has been the popular question in the java interviews. Because, stop() method has been deprecated for some safety reasons. As stop() method has been deprecated, interviewer will be interested in what logic you will be using to stop a thread. There are two ways through which you can stop a thread in java. One is using boolean variable and second one is using interrupt() method. In this post, we will discuss both of these methods.

How To Stop A Thread In Java Using A boolean Variable?

In this method, we declare one boolean variable called flag in a thread. Initially we set this flag as true. Keep the task to be performed in while loop inside the run() method by passing this flag. This will make thread continue to run until flag becomes false. We have defined stopRunning() method. This method will set the flag as false and stops the thread. Whenever you want to stop the thread, just call this method. Also notice that we have declared flag as volatile. This will make thread to read its value from the main memory, thus making sure that thread always gets its updated value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class MyThread extends Thread
{
    //Initially setting the flag as true
    
    private volatile boolean flag = true;
    
    //This method will set flag as false
    
    public void stopRunning()
    {
        flag = false;
    }
    
    @Override
    public void run()
    {
        //Keep the task in while loop
        
        //This will make thread continue to run until flag becomes false
        
        while (flag)
        {
            System.out.println("I am running....");
        }
        
        System.out.println("Stopped Running....");
    }
}
public class MainClass
{  
    public static void main(String[] args)
    {
        MyThread thread = new MyThread();
        
        thread.start();
        
        try
        {
            Thread.sleep(100);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        
        //call stopRunning() method whenever you want to stop a thread
        
        thread.stopRunning();
    }   
}

Output :

I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
Stopped Running….

How To Stop A Thread In Java Using interrupt() Method?

In this method, we use interrupt() method to stop a thread. Whenever you call interrupt() method on a thread, it sets the interrupted status of a thread. This status can be obtained by interrupted() method. This status is used in a whileloop to stop a thread.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MyThread extends Thread
{   
    @Override
    public void run()
    {
        while (!Thread.interrupted())
        {
            System.out.println("I am running....");
        }
        
        System.out.println("Stopped Running.....");
    }
}
public class MainClass
{  
    public static void main(String[] args)
    {
        MyThread thread = new MyThread();
        
        thread.start();
        
        try
        {
            Thread.sleep(100);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        
        //interrupting the thread
        
        thread.interrupt();
    }   
}

Output :

I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
I am running….
Stopped Running…..

How Volatile in Java works? Example of volatile keyword in Java

How to use Volatile keyword in Java
What is volatile variable in Java and when to use  the volatile variable in Java is a famous multi-threading interview question in Java interviews. Though many programmers know what is a volatile variable but they fail on second part i.e. where to use volatile variable in Java as it’s not common to have a clear understanding and hands-on on volatile in Java. In this tutorial, we will address this gap by providing a simple example of the volatile variable in Java and discussing some when to use the volatile variable in Java. Anyway,  the volatile keyword in Java is used as an indicator to Java compiler and Thread that do not cache value of this variable and always read it from main memory. So if you want to share any variable in which read and write operation is atomic by implementation e.g. read and write in an int or a boolean variable then  you can declare them as volatile variable.

From Java 5 along with major changes like Autoboxing, Enum, Generics and Variable arguments , Java introduces some change in Java Memory Model (JMM), Which guarantees visibility of changes made from one thread to another also as “happens-before” which solves the problem of memory writes that happen in one thread can “leak through” and be seen by another thread.

The Java volatile keyword cannot be used with method or class and it can only be used with a variable. Java volatile keyword also guarantees visibility and ordering, after Java 5 write to any volatile variable happens before any read into the volatile variable. By the way use of volatile keyword also prevents compiler or JVM from the reordering of code or moving away them from synchronization barrier.

The Volatile variable Example in Java

To Understand example of volatile keyword in java let’s go back to Singleton pattern in Java and see double checked locking in Singleton with Volatile and without the volatile keyword in java.

/**
 * * Java program to demonstrate where to use Volatile keyword in Java. * In
 * this example Singleton Instance is declared as volatile variable to ensure *
 * every thread see updated value for _instance. 
 */
public class Singleton {
 private static volatile Singleton _instance; // volatile variable 
 public static Singleton getInstance(){ 
 if(_instance == null){ 
 synchronized(Singleton.class){ 
 if(_instance == null) 
 _instance = new Singleton(); 
 } 
 } 
 return _instance; 
 }
}}

If you look at the code carefully you will be able to figure out:
1) We are only creating instance one time
2) We are creating instance lazily at the time of the first request comes.

If we do not make the _instance variable volatile than the Thread which is creating instance of Singleton is not able to communicate other thread, that instance has been created until it comes out of the Singleton block, so if Thread A is creating Singleton instance and just after creation lost the CPU, all other thread will not be able to see value of _instance as not null and they will believe its still null.

Why? because reader threads are not doing any locking and until writer thread comes out of synchronized block, memory will not be synchronized and value of _instance will not be updated in main memory. With Volatile keyword in Java, this is handled by Java himself and such updates will be visible by all reader threads.

So in Summary apart from synchronized keyword in Java, volatile keyword is also used to communicate the content of memory between threads.

Let’s see another example of volatile keyword in Java

most of the time while writing game we use a variable bExit to check whether user has pressed exit button or not, value of this variable is updated in event thread and checked in game thread, So if we don’t use volatile keyword with this variable, Game Thread might miss update from event handler thread if it’s not synchronized in Java already. volatile keyword in java guarantees that value of the volatile variable will always be read from main memory and “happens-before” relationship in Java Memory model will ensure that content of memory will be communicated to different threads.

private boolean bExit; while(!bExit) { checkUserPosition(); updateUserPosition(); }

In this code example, One Thread (Game Thread) can cache the value of “bExit” instead of getting it from main memory every time and if in between any other thread (Event handler Thread) changes the value; it would not be visible to this thread. Making boolean variable “bExit” as volatile in java ensures this will not happen.

Also, If you have not read already then I also suggest you read the topic about volatile variable from Java Concurrency in Practice book by Brian Goetz, one of the must read to truly understand this complex concept.

When to use Volatile variable in Java

One of the most important thing in learning of volatile keyword is understanding when to use volatile variable in Java. Many programmer knows what is volatile variable and how does it work but they never really used volatile for any practical purpose. Here are couple of example to demonstrate when to use Volatile keyword in Java:

1) You can use Volatile variable if you want to read and write long and double variable atomically. long and double both are 64 bit data type and by default writing of long and double is not atomic and platform dependence. Many platform perform write in long and double variable 2 step, writing 32 bit in each step, due to this its possible for a Thread to see 32 bit from two different write. You can avoid this issue by making long and double variable volatile in Java.

2) A volatile variable can be used as an alternative way of achieving synchronization in Java in some cases, like Visibility. with volatile variable, it’s guaranteed that all reader thread will see updated value of the volatile variable once write operation completed, without volatile keyword different reader thread may see different values.

3) volatile variable can be used to inform the compiler that a particular field is subject to be accessed by multiple threads, which will prevent the compiler from doing any reordering or any kind of optimization which is not desirable in a multi-threaded environment. Without volatile variable compiler can re-order the code, free to cache value of volatile variable instead of always reading from main memory. like following example without volatile variable may result in an infinite loop

private boolean isActive = thread; public void printMessage(){ while(isActive){ System.out.println(“Thread is Active”); } }

without the volatile modifier, it’s not guaranteed that one Thread sees the updated value of isActive from other thread. The compiler is also free to cache value of isActive instead of reading it from main memory in every iteration. By making isActive a volatile variable you avoid these issue.

4) Another place where a volatile variable can be used is to fixing double checked locking in Singleton pattern. As we discussed in Why should you use Enum as Singleton that double checked locking was broken in Java 1.4 environment.

Important points on Volatile keyword in Java

  1. The volatile keyword in Java is only application to a variable and using volatile keyword with class and method is illegal.

    2. volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread’s local cache.

    3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).

    4. Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.

    5. From Java 5 changes to a volatile variable are always visible to other threads. What’s more, it also means that when a thread reads a volatile variable in Java, it sees not just the latest change to the volatile variable but also the side effects of the code that led up the change.

    6. Reads and writes are atomic for reference variables are for most primitive variables (all types except long and double) even without the use of volatile keyword in Java.

    7. An access to a volatile variable in Java never has a chance to block, since we are only doing a simple read or write, so unlike a synchronized block we will never hold on to any lock or wait for any lock.

    8. Java volatile variable that is an object reference may be null.

    9. Java volatile keyword doesn’t mean atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.

    10. If a variable is not shared between multiple threads, you don’t need to use volatile keyword with that variable.

Difference between synchronized and volatile keyword in Java

What is the difference between volatile and synchronized is another popular core Java question asked on multi-threading and concurrency interviews. Remember volatile is not a replacement of synchronized keyword but can be used as an alternative in certain cases. Here are few differences between volatile and synchronized keyword in Java.

1. The volatile keyword in Java is a field modifier while synchronized modifies code blocks and methods.

2. Synchronized obtains and releases the lock on monitor’s Java volatile keyword doesn’t require that.

3. Threads in Java can be blocked for waiting for any monitor in case of synchronized, that is not the case with the volatile keyword in Java.

4. Synchronized method affects performance more than a volatile keyword in Java.

5. Since volatile keyword in Java only synchronizes the value of one variable between Thread memory and “main” memory while synchronized synchronizes the value of all variable between thread memory and “main” memory and locks and releases a monitor to boot. Due to this reason synchronized keyword in Java is likely to have more overhead than volatile.

6. You can not synchronize on the null object but your volatile variable in Java could be null.

7. From Java 5 writing into a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire

In short, volatile keyword in Java is not a replacement of synchronized block or method but in some situation is very handy and can save performance overhead which comes with use of synchronization in Java. If you like to know more about volatile I would also suggest going thorough FAQ on Java Memory Model here which explains happens-before operations quite well.

Intricacies of Multi-Threading in Java

Multi-threading represents a very intriguing topic, even after years of research and development for high quality, robust, and efficient software. With equal emphasis on hardware improvements and the software that runs on it – we have newer paradigms for parallelism. The most important yet basic concepts are the ones which I present here. I then explain the intricacies of multi-threading in the Java programming language. Some of these are newer features and supported only from the Java Platform Standard Edition 5.0. Let us start with a quick overview and understanding of the core concepts.

Thread Concepts in Operating Systems           

Thread: A thread is a lightweight process, but it differs from a process in multiple ways. The primary features of a thread are that it creates a sense of execution of processes concurrently; it effectively distributes work and executes a single task, it can be used to schedule and asynchronously execute tasks, it has a more effective context switching mechanism than processes, and it shares the memory space along with other threads yet can have its own storage

Critical Section: The critical section of the code is identified as the focus area that will be accessed by multiple threads concurrently and can modify the state. Since there is concurrent modification while sharing a resource, there needs to be controlled access.

Semaphores: Semaphore is a resource count that can be used to control access to a shared resource, especially in a multi-threaded environment.

Mutex: Mutex is a synchronization construct that allows only one thread a time to use a resource and has ownership associated with it.

Monitor: A synchronization construct that allows both mutual exclusion and the ability to wait for a condition to be true.

Deadlocks: While accessing the critical section of the code, there might be situations where multiple shared resources are accessed by multiple threads. In such scenarios, when a single thread requires access to a shared resource, it may first need to relieve the currently shared resource that is holding. It may also be true of another concurrently executing thread with respect to the same resources. When such mutual exclusion cannot be achieved, it leads to a Deadlock.

Deadlock Prevention: The techniques involved in preventing deadlock conditions from arising constitute Deadlock Prevention.

Deadlock Handling: Detection of deadlocks and its removal constitute Deadlock Handling.

Reentrancy: When a method or subroutine can be reentered without completing its previous invocation.

Image title

Thread Interfaces or Classes or in Java

Thread: The important methods of Thread Class are explained and usage shown in the code samples. The most confusing and common errors even for experienced Java programmers in multi-threading is in understanding locks. I have provided the status of locks on shared objects during each of these methods.

Runnable: An alternate way to create a Thread is by implementing this interface. One can create a thread in Java by either of implementing a Runnable interface or extending the Thread class. The programmer will have to override the run() method from this interface to implement logic.

  • start(), Lock Status: Can Acquire Locks; This is the method called to schedule a thread to run. Once scheduled and a CPU cycle is available the thread actually runs.
  • run(), Lock Status: Can Acquire Locks; It is implicitly called by the Thread runtime to start executing a thread.
  • yield(), Lock Status: Locks Held; This method yields or transfers control to another thread of equal priority. It does not provide any guarantee regarding which thread it will transfer control to or whether it will at all. The code snippet below also shows how to create a Thread by extending the Thread class.
  • sleep(), Lock Status: Locks Held; This method causes the current thread in execution to pause execution for a given time period. The time period is specified in milliseconds. It throws an interrupted exception, which needs to be handled by the programmer.
  • join(), Lock Status: Locks Held; This leads to an execution mode where all threads join at the end of the current thread. In other words, the current thread is taken to completion before switching to another thread. It throws an interrupted exception, which the programmer has to handle.
  • suspend(), Lock Status: Locks Held, Deprecated.
  • resume(), Lock Status: Locks Held, Deprecated; These thread methods are deprecated as it could lead to deadlocks and frozen processes. This is especially when the thread that has to resume a suspended thread requires access to the shared resource or lock held by the suspended thread before invoking resume().
  • stop(), Lock Status: Locks Released, Deprecated; This thread method is deprecated as it produced inconsistent states due to damaged objects. I am not providing the code sample as it is pretty straight forward usage – but I will not recommend the use of these methods, even if using a very old compiler version.

Object in Java

The Object class in Java inherently contains the methods that can control access to this object, especially in shared or multi-threaded applications.

  • wait(), Lock Status: Current Object Lock Released, OtherLocks Held; The wait() method causes the current thread to pause execution and move to a wait state. It also releases the lock that it holds on the current object but retains all other locks on other objects.
  • notify(), Lock Status: Acquisition of Lock by an Arbitrary Waiting Thread; The notify() method notifies an arbitrary thread that is waiting to obtain a lock on the currently shared object.
  • notifyAll(), Lock Status: Acquisition of Lock by an Arbitrary Waiting Thread; The notifyAll() counterpart of this method notifies all threads that are waiting to acquire a lock on the shared object.

Note on locks: You may use this thought process whenever you think of Locks or Monitors in Java – Any concurrent modification by Threads should not lead to a damaged object. The only exception being the wait() and notify() mechanisms which may cause changes to a shared resource or object before swapping or switching control. A damaged object is one in which undesirable or corruptible changes have occurred to the state.

synchronized: In Java, the synchronized keyword is used to control access to the critical section of the code. Alternatively, it is the implementation of Thread Monitors in Java. The synchronized keyword can be applied to both static methods or to instance level methods or blocks. When a thread enters a synchronized block or method, it obtains the lock on that class or object. In the case of static synchronized methods, a single lock is held at the class level and is different from an instance level lock that is held per instance of the class. The synchronized keyword provides the necessary mutual exclusion on a shared resource. wait(), notify(), and notifyAll() can only be called in synchronized blocks or methods. Mutexes are not inherently supported in Java. 

Case Study: Design a multi-threaded system that has a shared resource that can take only two values; 0 or 1. It should have two methods, one each for incrementing and decrementing that are called by two threads concurrently. One of the threads can only constantly increment and another can only constantly decrement. Their operations should be mutually exclusive.

Solution: It is a simplified version of the Producer-Consumer problem.

package org.csi_india.programming.workbench.multithreading;
public class CSIDecrementer implements Runnable {
    CSISharedObject csiSharedObject;
    CSIDecrementer(CSISharedObject csiSharedObject) {
        this.;
    }
    public void run() {
        while(true) csiSharedObject.decrementerAccess();
    }
}
package org.csi_india.programming.workbench.multithreading;
public class CSIIncrementer implements Runnable {
    CSISharedObject csiSharedObject;
    CSIIncrementer(CSISharedObject csiSharedObject) {
        this.;
    }
    public void run() {
        while(true) csiSharedObject.incrementerAccess();
    }
}
package org.csi_india.programming.workbench.multithreading;
public class CSIWorkbench extends Thread {
    public static void main(String[] args) {
        CSISharedObject csiShared=new CSISharedObject();
        Thread csiThread01=new Thread(new CSIIncrementer(csiShared));
        csiThread01.start();
        Thread csiThread02=new Thread(new CSIDecrementer(csiShared));
        csiThread02.start();
    }
}
package org.csi_india.programming.workbench.multithreading;
public class CSISharedObject {
    // access from within this class only
    private int;
    public synchronized void decrementerAccess() {
        try {
            if (x = ) {
                x--;
                notify();
            } else {
                wait();
            }
        } catch (InterruptedException e) {
            System.out.println("thread interrupted");
        }
    }
    public synchronized void incrementerAccess() {
        try {
            if (x = ) {
                x++;
                notify();
            } else {
                wait();
            }
        } catch (InterruptedException e) {
            System.out.println("thread interrupted");
        }
    }
}

You may refer to the following section, as these tools were introduced only since JDK 5 and 6. They provide a more granular or controlled access for asynchronous task execution in Java.

  • Callable: Another class similar to Runnable, whose instances are potentially executed by another Thread.
  • Executors: A helper interface for creation of thread pool.
  • ExecutorService: An asynchronous task executor that can be used to submit Runnable or Callable tasks for execution and then to track their status through a Future object.
  • Future: An object return from task submission to an asynchronous task executor using which a task state can be monitored.
  • AtomicInteger: A type of Integer object in Java that performs concurrent lock-free updates using hardware instructions.

Case Study: Design an asynchronous task executor modeled as a thread pool executor.

Solution: It is a simplified version of the Producer-Consumer problem.

Most of the below classes were introduced since JDK 7. They provide an alternate and simpler way of programming multi-threaded applications in Java.

Condition: Condition factors out the Object monitor methods (wait, notify and notifyAll() into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods. Condition is a Java interface.

signal(): Wakes up one waiting Thread.

signalAll(): Wakes up all waiting Threads.

await(): Causes the current Thread to wait until it is signaled or interrupted. Lock: Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. Lock is an interface.

ReentrantLock: A reentrant mutual exclusion lock with the same basic behavior as implicit monitor lock. It is a concrete implementation of Lock.

Happy Multi-Threading in Java!

Java Threads Important Points.

Defining and instantiating and Starting Threads:

  • Threads can be created by extending Thread and overriding the public void run () method.
  • Thread objects can also be created by call the thread class constructor that takes a Runnable argument, the Runnable object is said to be the target of the thread.
  • You can call start () on a thread only once. If start() is called more than once on a thread object it will throw Runtime exception
  • It is legal to create many thread objects using the same Runnable object as the target.
  • When a thread object is created, it does not become a thread of until its start () method is invoked. When a thread object exists but hasn’t been started. It is in the new state and is not considered alive.

Transitioning between the Thread States:

  • Once a new thread is started, it will always enter the Runnable state.
  • The thread scheduler ca move thread back and forth between the Runnable state and the running state.
  • For a typical single-processer machine, only one thread can be running at a time, although many threads may be in Runnable state.
  • There is no guarantee that the order in which threads were stated determines the order in which they’ll run.
  • There’s no guarantee threads will take turns in any fair way. It’s up to the thread scheduler, as determined by the particular virtual machine implementation. If you want a guarantee that your threads will take turns regardless of the underlying JVM. You can use the sleep () method.
  • This prevents one thread from hanging the running process while another thread serves. (In most cases though yield () works well enough to encourage your threads to play together nicely).
  • A running thread may enter a blocked / waiting state because it can’t acquire the lock for a synchronized block of code.
  • When the sleep or wait is over, or an objects lock become available, the thread can only reenter the Runnable state. It will go directly from waiting to running (well, for all practical purpose only).
  • A dead thread cannot be started again.

Sleep, Yield and join:

  • Sleeping is used to delay execution fo a period of time, and no locks are released when a thread goes to sleep.
  • A sleeping thread guaranteed to sleep for at least the time specified in argument to the sleep () method (unless it is interrupted), but there is no guarantee as to when the newly awakened thread will actually return to running.
  • The sleep () method is static method that sleeps the currently executing thread’s state. One thread cannot tell another thread to sleep.
  • The set priority() method is used on thread objects to give threads a priority of between 1(low) and 10(high), although priorities are not guaranteed, and not all JVMs recognize 10 distinct priority levels, some levels may be treated as effectively
  • If not explicitly set, a thread’s priority will have the same priority as priority of the thread created it.
  • The yield () method may cause a running thread to blackout if there are Runnable threads of same priority.
  • There is no guarantee that those will happen, and there is no guarantee that the thread selected to run. A thread might yield and then immediately renter the running state.
  • The closest thing to guarantee is that at any given time when the thread is running it will usually not have a lower priority than a thread in the Runnable state.
  • If a low-priority thread running and a high-priority thread enter Runnable, the JVM will usually preempt the running low-priority thread and put the high-priority thread in.
  • When one thread calls join () method of another thread, the currently running thread will wait the thread it joins which has completed.
  • Think the join () method as saying “Hay thread, I want to join on to the end of you, let me know when you are done so I can enter the Runnable state.”

Concurrent Access Problems and Synchronized Threads:

  • Synchronized methods prevent more than one thread from accessing an object’s critical method code simultaneously.
  • You can use the synchronized keyword as a method modifier, or to start a synchronized block of code.
  • To synchronize a block of code ( in other words, a scope smaller than the whole method) you must specify an argument that is the object whose lock you what to synchronize code.
  • While only one thread can be accessing synchronized code of a particular instance multiple threads can still access same objects unsynchronized code.
  • When a thread gets to sleep, its locks will be unavailable to other threads.
  • Static methods can be synchronized, using the local from java.lang.Class instance representing the class.

Communicating with Objects by Waiting and Notifying:

  • The wait() method lets a thread say, “there is nothing for me to do now, so out me in your out pool and notify me when something happens that I care about”. Basically a wait () call means “wait me in your pool” or “add me to your waiting pool”.
  • The notify () method is used to send a signal to one and only one of the threads that are waiting in that same object’s waiting pool.
  • The notify method can NOT specify which waiting thread to notify.
  • The method notifyAll () works in the same way as notify (), only it sends the signal to all of the threads waiting on the object.
  • All three methods wait (), notify (), notifyAll () must be called for within a synchronized context. A thread invokes wait () or notify () on a particular object, and the thread must currently hold the lock on the object.

Deadlocked Threads:

  • Deadlocking is when thread execution grinds to a halt because the code is waitng for locks to be removed from objects.
  • Deadlocking can occur when a locked object attempts to access another locked object that is trying to access the first locked object.
  • In other words, both threads are waiting for each other’s locks to be released; therefore, locks will never released
  • Deadlocking is bad, don’t do it.