Tuesday, 30 June 2015

isAlive and join method in Java multi-threading

What if we want to know when a thread has ended? Java provides two ways to find that –

  • isAlive()
  • join()

isAlive() method

This method is the member of the Thread class and its general form is –

public final boolean isAlive()

isAlive() method tests if the thread it is called upon is alive. A thread is alive if it has been started and has not yet died. The isAlive( ) method returns true if the thread upon which it is called is still running, otherwise it returns false.

join() method

Join() method is used when you want to wait for the thread to finish. Its general form is –

public final void join() throws InterruptedException

This method waits until the thread on which it is called terminates. There are three overloaded join functions.

  • public final void join() - Waits indefinitely for this thread to die.
  • public final void join(long millis) - Waits at most  millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
  • public final void join(long millis, int nanos) - Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

Example code using join and isAlive()

Let’s say there is a scenario where in a code multiple threads are spawned to do some heavy computation and only when the processing is done a message should be displayed to a user that “Processing is done”.
Now first let’s try to do something like it without using join.

class MyRunnableClass implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 5 ; i++){
            System.out.println(Thread.currentThread().getName() + " i - " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }    
}
public class JoinExample {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnableClass(), "t1");
        Thread t2 = new Thread(new MyRunnableClass(), "t2");
        Thread t3 = new Thread(new MyRunnableClass(), "t3");
         
        t1.start();
        t2.start();
        t3.start();
        
        System.out.println("t1 Alive - " + t1.isAlive());
        System.out.println("t2 Alive - " + t2.isAlive());
        System.out.println("t3 Alive - " + t3.isAlive());
        
        /*try {
            t1.join();        
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
        System.out.println("t1 Alive - " + t1.isAlive());
        System.out.println("t2 Alive - " + t2.isAlive());
        System.out.println("t3 Alive - " + t3.isAlive());*/        
        System.out.println("Processing finished");
    }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
Processing finished
t3 i - 0
t1 i - 0
t2 i - 0
t3 i - 1
t1 i - 1
t2 i - 1
t2 i - 2
t1 i - 2
t3 i - 2
t3 i - 3
t1 i - 3
t2 i - 3
t3 i - 4
t1 i - 4
t2 i – 4

Here it can be seen that the message is displayed much before the actual processing has finished.

Now let’s uncomment the code related to join and run the program again.

class MyRunnableClass implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 5 ; i++){
            System.out.println(Thread.currentThread().getName() + " i - " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
}
public class JoinExample {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnableClass(), "t1");
        Thread t2 = new Thread(new MyRunnableClass(), "t2");
        Thread t3 = new Thread(new MyRunnableClass(), "t3");
         
        t1.start();
        t2.start();
        t3.start();
        
        System.out.println("t1 Alive - " + t1.isAlive());
        System.out.println("t2 Alive - " + t2.isAlive());
        System.out.println("t3 Alive - " + t3.isAlive());
        
        try {
            t1.join();        
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        System.out.println("t1 Alive - " + t1.isAlive());
        System.out.println("t2 Alive - " + t2.isAlive());
        System.out.println("t3 Alive - " + t3.isAlive());
        
        System.out.println("Processing finished");
    }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
t2 i - 0
t3 i - 0
t1 i - 0
t1 i - 1
t2 i - 1
t3 i - 1
t3 i - 2
t1 i - 2
t2 i - 2
t1 i - 3
t2 i - 3
t3 i - 3
t2 i - 4
t3 i - 4
t1 i - 4
t1 Alive - false
t2 Alive - false
t3 Alive - false
Processing finished

Now see how message is displayed only when the processing is actually finished and all the threads are terminated. The second print statements using isAlive() method confirms that the threads are not running any more.

That's all for this topic isAlive and join method in Java multi-threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What if run() method called directly instead of start() method
  2. Can we start the same thread twice in Java
  3. Creating thread in Java
  4. Synchronization in Java multithreading
  5. Race condition in Java multi-threading
  6. Java Multi-threading interview questions

You may also like -

Race condition in Java multi-threading

Race condition occurs in a multi-threaded environment when more than one thread try to access a shared resource (modify, write) at the same time. Note that it is safe if multiple threads are trying to read a shared resource as long as they are not trying to change it. Since multiple threads try to race each other to finish executing a method thus the name race condition.

Note that multiple threads executing inside a method is not a problem in itself, problem arises when they try to access the same resource. Examples of shared resources are class variables, DB record in a table, writing in a file.

Let’s see one example where we have a shared instance variable, as we have three threads sharing the same object of the class.

This instance variable c is incremented and decremented so every thread should leave it in the state it initially was i.e. if c is zero in the start, incrementing it will make it 1 and decrementing it will make it zero again.

Here some delay is simulated using sleep(), as in a real production system there may be many processes running and many users might be accessing the same application at any given time. In that kind of scenario we can’t be sure of when context switching will happen among the threads contending for CPU-cycle. That’s why race condition related bugs are very difficult to find and you may not be even able to reproduce them as that kind of context-switching may not happen when you are trying to reproduce the race condition related error.

Example of race condition

class Counter  implements Runnable{
    private int c = 0;

    public void increment() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        c++;
    }

    public void decrement() {    
        c--;
    }

    public int getValue() {
        //System.out.println("in getValue method ");
        
        return c;
    }
    
    @Override
    public void run() {
        this.increment();
        System.out.println("Value for Thread After increment " + Thread.currentThread().getName() + " " + this.getValue());
        this.decrement();
        System.out.println("Value for Thread at last " + Thread.currentThread().getName() + " " + this.getValue());
        
    }
}


public class RaceConditionDemo{
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(counter, "Thread-1");
        Thread t2 = new Thread(counter, "Thread-2");
        Thread t3 = new Thread(counter, "Thread-3");
        t1.start();
        t2.start();
        t3.start();
    }    
}

Output

Value for Thread After increment Thread-2 3
Value for Thread at last Thread-2 2
Value for Thread After increment Thread-1 2
Value for Thread at last Thread-1 1
Value for Thread After increment Thread-3 1
Value for Thread at last Thread-3 0

It can be seen how the shared variable c is giving wrong values.

To fix the race condition we need to have a way to restrict resource access to only one thread at a time. We have to use synchronized keyword to synchronize the access to the shared resource. Let’s see the same example again with proper synchronization to avoid race condition.

//This class' shared object will be accessed by threads
class Counter  implements Runnable{
    private int c = 0;

    public  void increment() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        c++;
    }

    public  void decrement() {    
        c--;        
    }

    public  int getValue() {
        //System.out.println("in getValue method ");
        
        return c;
    }
    
    @Override
    public void run() {
        synchronized(this){
            this.increment();
            System.out.println("Value for Thread After increment " + Thread.currentThread().getName() + " " + this.getValue());
            this.decrement();
            System.out.println("Value for Thread at last " + Thread.currentThread().getName() + " " + this.getValue());
        }
        
    }
}


public class RaceConditionDemo{
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(counter, "Thread-1");
        Thread t2 = new Thread(counter, "Thread-2");
        Thread t3 = new Thread(counter, "Thread-3");
        t1.start();
        t2.start();
        t3.start();
    }    
}

Output

Value for Thread After increment Thread-2 1
Value for Thread at last Thread-2 0
Value for Thread After increment Thread-3 1
Value for Thread at last Thread-3 0
Value for Thread After increment Thread-1 1
Value for Thread at last Thread-1 0

It can be seen from the output how threads are accessing the shared resource one at a time now. Synchronizing the access with in the run() method made it happen.

Points to note -

  • A code block that has a shared resource and may lead to race conditions is called a critical section.
  • Race conditions can be avoided by proper thread synchronization in critical sections.

That's all for this topic Race condition in Java multi-threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Synchronization in Java multithreading
  2. What if run() method called directly instead of start() method
  3. isAlive() & join() methods in Java multithreading
  4. Why wait(), notify() and notifyAll() methods are in Object class
  5. Deadlock in Java multi-threading
  6. Java Multi-threading interview questions

You may also like -

Saturday, 27 June 2015

Thread priorities - Java multithreading

When we talk about thread we use terms like concurrent threads or threads executing concurrently. But in reality threads also run one at a time (at least in a single CPU system), threads are given CPU cycle in a time shared manner to simulate concurrency.
The order in which multiple threads will be executed is decided by thread scheduler and thread priority is used by the thread scheduler to make that decision.

Java Thread Priority

When a Java thread is created, it inherits its priority from the thread that created it. Thread's priority can be modified at any time after its creation using the setPriority() method which is a member of Thread class.

General form

public final void setPriority(int newPriority)

Here newPriority specifies the new priority setting for the calling thread. The priority level ranges from 1 (least important) to 10 (most important) and the default priority level is 5 .

In Thread class, three constants are provided to define min, max and default priority for a thread.

     /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

    /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

Let's write some code to see priorities in action. First we'll write a program where no priorities are set so each thread will have the default priority.

Example code

//This class' shared object will be accessed by threads
class LoopValues implements Runnable{

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
        
    }
}

public class ThreadPriorityDemo {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new LoopValues(), "Thread-1");
        Thread thread2 = new Thread(new LoopValues(), "Thread-2");            
        thread1.start();
        thread2.start();           
        try {
            
            //Wait for the threads to finish
            thread1.join();
            thread2.join();
            
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
            
        System.out.println("Done with looping values");
    }
}

Output

Thread-1 : 1
Thread-1 : 2
Thread-1 : 3
Thread-1 : 4
Thread-2 : 1
Thread-2 : 2
Thread-2 : 3
Thread-2 : 4
Thread-2 : 5
Thread-2 : 6
Thread-2 : 7
Thread-2 : 8
Thread-2 : 9
Thread-2 : 10
Thread-1 : 5
Thread-1 : 6
Thread-1 : 7
Thread-1 : 8
Thread-1 : 9
Thread-1 : 10
Done with looping values

Here it can be seen that output has a mix of both the threads. Please note that the output may vary with each run.

Now we'll set the priorities so that one thread has the max priority(10) and another has the least priority(1).

//This class' shared object will be accessed by threads
class LoopValues implements Runnable{

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
        
    }
}

public class ThreadPriorityDemo {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new LoopValues(), "Thread-1");
        Thread thread2 = new Thread(new LoopValues(), "Thread-2");      
        thread1.setPriority(Thread.MAX_PRIORITY);
        thread2.setPriority(Thread.MIN_PRIORITY);
        thread1.start();
        thread2.start();           
        try {
            
            //Wait for the threads to finish
            thread1.join();
            thread2.join();
            
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
            
        System.out.println("Done with looping values");
    }

}

Output

Thread-1 : 1
Thread-1 : 2
Thread-1 : 3
Thread-1 : 4
Thread-1 : 5
Thread-1 : 6
Thread-1 : 7
Thread-1 : 8
Thread-1 : 9
Thread-1 : 10
Thread-2 : 1
Thread-2 : 2
Thread-2 : 3
Thread-2 : 4
Thread-2 : 5
Thread-2 : 6
Thread-2 : 7
Thread-2 : 8
Thread-2 : 9
Thread-2 : 10
Done with looping values

It can be seen that the thread which has the highest priority finishes first then the second thread starts its execution. Please note that even with this priority setting there may be a mixed output or the thread with the min priority may execute first. That brings us to the next section why we can't rely that much on thread priority.

Caution with thread priorities

Thread priority rules are dependent on the host platform (native OS). Host platform may have different priorities for the threads which may be more than what priorities are defined in Java or may be less than that. Java run time system maps the thread priorities to the priority levels of the host platform. So JVM may schedule a thread according to the priority defined in Java multithreading but when that thread actually gets the CPU cycle also depends upon the priorities defined by the host platform.

That's all for this topic Thread priorities in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Multi-threading interview questions
  2. Creating thread in Java
  3. Can we start the same thread twice in Java
  4. What if run() method called directly instead of start() method
  5. Thread states in Java multithreading
  6. Synchronization in Java multithreading

You may also like -

Friday, 26 June 2015

Synchronization in Java multithreading

In a multithreaded environment when more than one thread are trying to access a shared resource we need to have some way to ensure that the resource will be used by only one thread at a time. The process by which it is ensured is called synchronization.

For achieving synchronization in Java concept of monitor is used. Every object created in Java has one associated monitor (mutually exclusive lock). Only one thread can own a monitor at any given time. When a code is within a synchronized method (or synchronized block) compiler provides instructions to acquire the lock on the specified object before any thread executes the code which is with in a synchronized method (or synchronized block).
When any thread acquires a lock it is said to have entered the monitor. All other threads which need to execute the same shared piece of code (locked monitor) will be suspended until the thread which initially acquired the lock releases it.

In case of static members to have proper synchronization we need to have a synchronized static method. As we know that every class loaded by the JVM is essentially an object of type Class. So, in that case too, monitor of the object is acquired but that is the monitor of the Class object that represents the class to which the static method belongs. We'll go into instance method and static method synchronization in detail very soon.

Where can we use synchronized keyword

The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements (also known as synchronized blocks). This can be further divided into use with instance methods and static methods. So, essentially we can have four different ways synchronized keyword can be used.

  • instance method
  • An enclosed code block with in an instance method (Synchronized block).
  • static method
  • An enclosed code block with in a static method.

Let's see where and why we should use a specific type of synchronized method or block.

Synchronized Instance Method

We can synchronize a method by appending synchronized keyword within a method signature.

General Form of synchronized instance method

Public synchronized void method_name(parameter_list){
}

Let's see an example code where first we write the same code with synchronizing a method and later synchronize the method.

// This class' shared object will be accessed by threads
class Message{
 public void displayMsg(String msg){
   System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
   System.out.println("**" + msg); 
   try {
      Thread.sleep(10);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   System.out.println("*");
 }
}
 
class MyClass implements Runnable{
  Thread t;
  Message msg;
  String message;
  MyClass(Message msg, String str){ 
    this.msg = msg;
    this.message = str;
    // creating threads, 4 threads will be created 
    // all sharing the same object msg
    t = new Thread(this);
    t.start();
  }
  @Override
  public void run() {
     msg.displayMsg(message);
  }
}

public class SynchronizedDemo {
  public static void main(String[] args) {
    Message msg = new Message();
    MyClass mc1 = new MyClass(msg, "I");
    MyClass mc2 = new MyClass(msg, "am");
    MyClass mc3 = new MyClass(msg, "not");
    MyClass mc4 = new MyClass(msg, "synchronized");
  }
}

Output

I got the following output, for you output may differ as it depends upon which thread is picked first.

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
**synchronized
Inside displayMsg method Thread-1
**am
Inside displayMsg method Thread-2
**not
**I
*
*
*
*

It can be seen how output has all jumbled, because all the 4 threads share the same object and a delay has been simulated using sleep. That's why the last asterisks are all coming together because sleep() method is used just before that.

If we use synchronize keyword with the method only a single thread will access the method at the given time. In that case the displayMsg() method will look like -

class Message{
    public synchronized void displayMsg(String msg){
        System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
        System.out.print("**" + msg);        
        try {
            Thread.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("*");
    }
}

Output

Inside displayMsg method Thread-0
**I*
Inside displayMsg method Thread-1
**am*
Inside displayMsg method Thread-2
**not*
Inside displayMsg method Thread-3
**synchronized*

Now it can be seen how one thread finishes its execution then only another thread starts its execution of the method. Though which thread is picked first is up to the scheduler that's why the message may not print correctly but the point here is that whichever thread enters the synchronized method that finishes then only the next thread starts its execution.

Please note that a synchronized instance method is synchronized on the instance(object) of the class. So, if a class has more than one object then one thread at a time can enter each object's synchronized method.

Synchronized statement(block) in instance method

It is not always needed to synchronize the whole method, let's say we have a 100 line code method, out of which critical section (shared resource) is only 7 lines then it makes sense to synchronize only those 7 lines rather than synchronizing the whole method. That way we can improve performance.
synchronized statements must specify the object that provides the intrinsic lock.

General Form of synchronized Synchronized statement (block)

Synchronized(object_reference){
// code block
}

Though it is also possible to synchronize on a string but it is considered a bad idea as "Literal strings within different classes in different packages likewise represent references to the same String object." See this for reference - http://www.javalobby.org/java/forums/t96352.html

If we use the same example used with instance method it can be changed to use synchronized block like this -

//This class' shared object will be accessed by threads
class Message{
    public void displayMsg(String msg){
        System.out.println("Inside displayMsg method " + Thread.currentThread().getName());
        synchronized(this){
            System.out.print("**" + msg);        
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("*");
        }
    }
}

Output

Inside displayMsg method Thread-0
Inside displayMsg method Thread-3
Inside displayMsg method Thread-2
Inside displayMsg method Thread-1
**I*
**am*
**not*
**synchronized*

It can be seen from the output how the first print statement is executed by all the threads as that is not inside the synchronized block. After that only a single thread executes at a time and finishes its execution only then another thread enters.

Synchronized static method

With instance method synchronization threads are executed one thread per instance. That may create problems when we have more than one instance of the same class.

Let's see with the help of an example what problem we may face in case we don't use static synchronization.

//This class' shared object will be accessed by threads
class Message1{
  public synchronized void displayMsg(){
    System.out.println("In run method " + Thread.currentThread().getName()); 
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
        Thread.sleep(50);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } 
  }
}

class MyClass1 implements Runnable{
  Thread t; 
  Message1 msg; 
  MyClass1(Message1 msg){
    this.msg = msg; 
    t = new Thread(this);
    t.start();
  }
  @Override
  public void run() {
    msg.displayMsg();
  }
}

public class SynchronizedDemo1 {
  public static void main(String[] args) { 
    Message1 msg1 = new Message1();
    Message1 msg2 = new Message1();
    // Two threads on msg1 object
    MyClass1 mc1 = new MyClass1(msg1);
    MyClass1 mc2 = new MyClass1(msg1);
    // Two threads on msg2 object
    MyClass1 mc3 = new MyClass1(msg2);
    MyClass1 mc4 = new MyClass1(msg2);
  }
}

Output

In run method Thread-1
Thread-1 i - 0
In run method Thread-3
Thread-3 i - 0
Thread-3 i - 1
Thread-1 i - 1
Thread-3 i - 2
Thread-1 i - 2
Thread-1 i - 3
Thread-3 i - 3
Thread-3 i - 4
Thread-1 i - 4
In run method Thread-2
Thread-2 i - 0
In run method Thread-0
Thread-0 i - 0
Thread-0 i - 1
Thread-2 i - 1
Thread-0 i - 2
Thread-2 i - 2
Thread-2 i - 3
Thread-0 i - 3
Thread-0 i - 4
Thread-2 i - 4

Here it can be seen that thread-0 and thread-1 are invoked on msg1 object where as thread-2 and thread-3 are invoked on msg-2 object. As we already know that if you are using synchronization on the instance methods then the thread will have exclusive lock one per instance. In the given example thread-0 and thread-1 will be synchronized using one monitor and thread-2 and thread-3 are synchronized using another monitor. We can see in the output thread-0 and thread-1 are not having any thread interference same way thread 2 and thread-3 are not having any thread interference but thread-1 and thread-3 are entering the synchronized method at the same time with their own respective locks. Lock hold by thread-1 will stop thread-0 from entering the synchronized method as they are working on the same instance. But it cannot stop thread-2 or thread-3 as they are working on another instance.

In these kinds of scenarios if we still need a single thread to have access then we have to use static synchronized method or block to have synchronization at the class level rather than on the instance level.

Code with static synchronized method

We just need to change the displayMsg() method to look like -
//This class' shared object will be accessed by threads
class Message1{
  public static synchronized void displayMsg(){
    System.out.println("In run method " + Thread.currentThread().getName()); 
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
         Thread.sleep(50);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
    } 
  }
}

Ouput

In run method Thread-0
Thread-0 i - 0
Thread-0 i - 1
Thread-0 i - 2
Thread-0 i - 3
Thread-0 i - 4
In run method Thread-2
Thread-2 i - 0
Thread-2 i - 1
Thread-2 i - 2
Thread-2 i - 3
Thread-2 i - 4
In run method Thread-3
Thread-3 i - 0
Thread-3 i - 1
Thread-3 i - 2
Thread-3 i - 3
Thread-3 i - 4
In run method Thread-1
Thread-1 i - 0
Thread-1 i - 1
Thread-1 i - 2
Thread-1 i - 3
Thread-1 i - 4

It can be seen now how threads are executing one after another with any one thread holding the lock while it is executing.

Same way we can have static synchronized block where we need to synchronize the class object itself.

General form

Synchronized(CLASS_NAME.class)

In that case Message1 class will look like

//This class' shared object will be accessed by threads
class Message1{
  public static void displayMsg(){
    System.out.println("In run method " + Thread.currentThread().getName());
    synchronized(Message1.class){
      for(int i = 0; i < 5 ; i++){
        System.out.println(Thread.currentThread().getName() + " i - " + i);
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
           e.printStackTrace();
        }
      }
    }
  }
}

Output

In run method Thread-0
In run method Thread-3
Thread-0 i - 0
In run method Thread-1
In run method Thread-2
Thread-0 i - 1
Thread-0 i - 2
Thread-0 i - 3
Thread-0 i - 4
Thread-2 i - 0
Thread-2 i - 1
Thread-2 i - 2
Thread-2 i - 3
Thread-2 i - 4
Thread-1 i - 0
Thread-1 i - 1
Thread-1 i - 2
Thread-1 i - 3
Thread-1 i - 4
Thread-3 i - 0
Thread-3 i - 1
Thread-3 i - 2
Thread-3 i - 3
Thread-3 i - 4

See how the first statement is printed for all the threads as that statement is outside the synchronized block. But only thread-0 acquires the lock and starts its execution, all the other threads are suspended till the execution of thread-0 finishes.

That's all for this topic Synchronization in Java multithreading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Why wait(), notify() and notifyAll() must be called inside a synchronized method or block?
  2. Inter-thread communication using wait, notify and notifyAll
  3. Deadlock in Java multi-threading
  4. ThreadLocal class in Java
  5. Difference between ReentrantLock and Synchronized
  6. Java Multi-threading interview questions

You may also like -

Can we start the same thread twice in Java

According to Java Doc - http://docs.oracle.com/javase/8/docs/api/ description of start method in the Thread class says -

public void start()

Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Throws: IllegalThreadStateException - if the thread was already started.

Thus a Thread can only be started once and any attempt to start the same thread twice will throw IllegalThreadStateException.

In that case if we want to run the same thread again then we should make a new instance of the Thread and call start on it.

Example code of starting the same thread twice

public class ThreadTwiceStart implements Runnable {
    public static void main(String[] args) {
        // creating a thread 
        Thread t = new Thread(new ThreadTwiceStart(), "MyThread");
        t.start();
        // starting the same thread again
        t.start();
    }

    @Override
    public void run() {
        System.out.println("Thread started running " + Thread.currentThread().getName());    
    }
}

Output

Thread started running MyThread
Exception in thread "main" java.lang.IllegalThreadStateException
 at java.lang.Thread.start(Unknown Source)
 at org.netjs.example.ThreadTwiceStart.main(ThreadTwiceStart.java:9)

It can be seen how it has thrown IllegalThreadStateException if an attempt is made to start the same thread again.

If we have to start the same thread again we have to create a new thread object. This code will run fine -

public class ThreadTwiceStart implements Runnable {
    public static void main(String[] args) {
        // creating a thread 
        Thread t = new Thread(new ThreadTwiceStart(), "MyThread");
        t.start();
        t = new Thread(new ThreadTwiceStart(), "MyThread");        
        t.start();
    }

    @Override
    public void run() {
        System.out.println("Thread started running " + Thread.currentThread().getName());    
    }
}

Here a new thread object is created before calling the start method again thus this code will run without throwing any exception

That's all for this topic Can we start a thread twice in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference between Thread and Process in Java
  2. How to create thread in Java
  3. Thread states in Java multithreading
  4. What if run() method called directly instead of start() method
  5. Synchronization in Java multithreading
  6. Java Multi-threading interview questions

You may also like -

Wednesday, 24 June 2015

Best practices for exception handling in Java

  1. Use Specific Exceptions not Exception or Throwable -It is always better to throw specific exception (read specific sub-classes) rather than the more generic one (i.e. super class) like Throwable, Excpetion or RunTimeException. By doing that we can provide more information to the user what exactly went wrong and the code is also more readable, giving info about various exceptions it can throw rather than everything gobbled up by Exception or Throwable class.
    We should be specific when catching exceptions too. As Exp. For RunTimeException (unchecked exceptions) it is said that we should not catch them as they indicate application code errors. If we are catching Exception class directly we also catch RuntimeException as RuntimeException class inherits from Exception. Same way if we catch throwable directly like following that is also wrong -
    try {
    } catch(Throwable t) {
        t.printStackTrace();//Should not do this
    }
    

    Throwable is the superclass of all errors and exceptions in Java. Error is the superclass of all errors which are not meant to be caught by applications. Thus, catching Throwable would essentially mean that Errors such as system exceptions (e.g., OutOfMemoryError, StackOverFlowError) would also get caught. And, the recommended approach is that application should not try and recover from Errors such as these. Thus, Throwable and Error classes should not be caught. Only Exception and its subclasses should be caught.

  2. Throw Early or Fail-Fast - Since an exception stack trace shows the exact sequence of method calls till the point of exception, along with class name, file name and the line number where the exception occurs it becomes very important to throw exception as early as possible.

    Let's see what will happen if we don't do that.

     public class ShowFile {
        public static void main(String[] args) {
            File propFile = new File("");
    
            try
            {
                readFile(propFile);
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }        
            catch (EOFException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        
        private static void readFile(File filename) throws FileNotFoundException, EOFException{
            InputStream in = new FileInputStream(filename);        
        }
    }
     

    StackTrace

    java.io.FileNotFoundException: 
     at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at org.netjs.example.ShowFile.readFile(ShowFile.java:37)
        at org.netjs.example.ShowFile.main(ShowFile.java:18)
    

    In the stack trace it is a little difficult to point out the real origin of exception, seeing the stack trace it looks like problem is in FileInputStream though in reality it is the problem in the code that there is no check for space passed as file name.

    Let's see how we should do that.

    public class ShowFile {
        public static void main(String[] args) {
            File propFile = new File("");
            try
            {
                readFile(propFile);
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }        
            catch (IOException e)
            {
                e.printStackTrace();
            }
    
    
        }
        
        private static void readFile(File fileName) throws FileNotFoundException, EOFException, IllegalArgumentException{
            if(fileName == null || fileName.getPath().equals("")){
                throw new IllegalArgumentException("File Name not given");
            }
            InputStream in = new FileInputStream(fileName);
            
        }
    }
    

    StackTrace

    Exception in thread "main" java.lang.IllegalArgumentException: File Name not given
     at org.netjs.example.ShowFile.readFile(ShowFile.java:42)
     at org.netjs.example.ShowFile.main(ShowFile.java:18)
    

    It can be seen now with the check for the filename the stack trace gives precide information about the problem.

  3. Catch Late - In case of checked exceptions, it is enforced by Java compiler to either catch the exception or declare it in throws clause. So generally developer tends to catch it and do nothing except printing stacktrace or put a logger in order to avoid the compiler error. But that way we are not providing the true information of what exactly happened.

    Lets see an example -

    public class ShowFile {
        public static void main(String[] args) {
            File propFile = new File("");
            readFile(propFile);        
        }
        
        private static void readFile(File fileName) {
            InputStream in = null;
            try {
                in = new FileInputStream(fileName);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                in.read();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }        
        }
    }
    

    Stacktrace

    java.io.FileNotFoundException: 
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at org.netjs.example.ShowFile.readFile(ShowFile.java:41)
        at org.netjs.example.ShowFile.main(ShowFile.java:18)
    Exception in thread "main" java.lang.NullPointerException
        at org.netjs.example.ShowFile.readFile(ShowFile.java:47)
        at org.netjs.example.ShowFile.main(ShowFile.java:18)
    

    Here you can see that still of declaring the exception in throws clause and catching it at the point where it can be handled, try-catch block is used and the exception is caught using FileNotFoundException. If we see the stack trace it is not providing appropriate and precise information why the exception occurred.

    It is better to catch exception only when it can be handled appropriately. We can use throws clause to declare the exception and put the responsibility of catching them on the caller method. This way exception handling has been passed further up the call chain.

    public class ShowFile {
        public static void main(String[] args) {
            File propFile = new File("");
            try
            {
                readFile(propFile);
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }        
            catch (IOException e)
            {
                e.printStackTrace();
            }    
    
        }
        
        private static void readFile(File fileName) throws FileNotFoundException, IOException, IllegalArgumentException{
            if(fileName == null || fileName.getPath().equals("")){
                throw new IllegalArgumentException("File Name not given");
            }                 
            InputStream in = new FileInputStream(fileName);
            in.read();                
        }
    }
    
  4. Do not suppress exceptions - The whole idea of having a checked exception in Java is to give a chance to take some action to recover from the raised exception. So ignoring it by having empty braces in the catch block or just printing the stack trace or logging a checked exception and continue with the code is not a best practice.
     try {
        /* ... */
     } catch( Exception e ) {
     
     }
     
      try {
          /* ... */
      } catch( Exception e ) {
          // The exception thrown is lost
          Logger.info( "some exception occured" ); 
      }
      

    We should always avoid empty catch block that just consumes the exception and doesn't provide any meaningful details of exception for debugging purposes.

  5. Don't lose the original exception - Almost all the exception classes provide a constructor with the cause as parameter.
     public Exception(String message, Throwable cause)
    

    Always use the constructor with cause parameter to keep the original exception.
    As exp. - If some excpetion is thrown and you want to wrap it in a custom exception -

     
    catch (IllegalArgumentException exp) {
       throw new MyCustomException("Exception caught: " + e.getMessage());  //Incorrect way
    }
    

    This destroys the stack trace of the original exception, and is always wrong. The correct way of doing this is:

     
    catch (IllegalArgumentException exp) {
       throw new MyCustomException ("Exception caught: " , exp);  //Correct way
    }
    
  6. Custom Exception as checked Exception or Unchecked Exception - If user can take some action to recover from the expected error then make the custom exception a checked exception. On the other hand if user cannot do anything useful in case of error then make the custom exception as an unchecked exception (i.e. inheriting from RunTimeException).

    Most of the time only function of the custom exceptions is to log an error; in that case it should definitely be an unchecked exception.

  7. Follow Naming Convention for exceptions - When creating your own custom exception follow the already established naming convention for exception classes like always end the class name with Exception like NoSuchMethodExcpetion. MyAppException etc.
    Also try to keep the same type of exceptions in the same hierarchy like IOExcpetion is the base class exception for all the IO related exceptions.
  8. Java exception performance consideration - Exceptions do have an impact on the overall performance of the application so use them judiciously. Don't just throw and catch exceptions, if you can use boolean variable to indicate whether an operation was successful or not they try to return a Boolean variable to a caller program and decide the flow of the code based on the returned Boolean.
    Avoid unnecessary Exception handling by fixing root cause. Also check for null yourself before performing any operation or check the array length yourself rather than relying on ArrayIndexOutOfBoundException.
  9. Document the Exceptions Thrown - Use javadoc @throws to clearly specify the exceptions thrown by the method, it's very helpful when you are providing an interface to other applications to use.
  10. Exceptions should not be used for flow control - Raising and handling exception is an expensive operation and should be used for exceptional conditions only. Using it for flow control hits the overall performance and is a strict no no.
    Always check for array length and null values rather than relying on exception handling to do that.

    As example, always check for the array length in a loop

     
    for (int i=0; i < tempArray.length; i++) {
        // code using the tempArray
    }
    
    Don't rely on try-catch block
     
    try {
            for (int i=0; ; i++) {
              // code using the tempArray
            }
        } catch (ArrayIndexOutOfBoundsException ex) {
         …..
      }
    

    Check for null with in a code -

     
    if(obj != null){
        obj.getValue();
    }
    
    Or
    if(someMap.contains(obj)){
        someMap.get(obj);
    } 
    
    Is a better solution than having a try-catch block to do catch a null pointer exception.
    try{
        Obj.getValue()   
    }catch(RuntimeException exp){
       ....
    }
    
  11. Clean up the resources - If you are using resources like database connections, network connections or IO streams, make sure you clean them up using finally block or using the Java 7 ARM feature.
  12. Logging Exceptions and providing helpful message - We should always log exception messages and while throwing exception provide clear message so that caller will know easily why the exception occurred. Always append values in the exception message if possible.
    As example - If we are writing some code where some specific logic is there for senior citizens (Age greater than or equal to 60) if age is less than 60 then the method throws InvalidAgeException.
    In that case if exception is thrown then just saying in the message "Exception thrown from method METHOD_NAME" or "Invalid parameter" will not be as helpful as saying "Invalid age exception for " + {age} That way whoever is seeing the log can easily figure out what was the parameter given when the exception was thrown.
  13. Log and throw anti-pattern - Logging and throwing the exception with in a catch block is considered an error handling anti-pattern and should be avoided.
    catch (NoSuchFieldException exp) {
       LOG.error("Exception occurred", exp);
       throw exp;
    }
    
    Consider the above example code, doing both logging and throwing will result in multiple log messages in log files, for a single problem in the code. Whoever is going through the log will have to go through multiple logs for the same error rather than at one place in a log.
  14. Preserve loose coupling - One of the best practices for the exception handling is to preserve loose coupling. According to that an implementation specific checked exception should not propagate to another layer. As Exp. SQL exception from the DataAccessCode (DAO layer) should not propagate to the service (Business) layer. The general practice in that case is to convert database specific SQLException into an unchecked exception and throw it.
    catch(SQLException ex){
        throw new RuntimeException("DB error", ex);
    }
    

That's all for this topic Best practices for exception handling in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!



Related Topics

  1. finally block
  2. final Vs finally Vs finalize
  3. Creating custom exception class
  4. Multi catch statement in Java 7
  5. try-with-resources in Java 7
  6. Java Exception Handling interview questions

You may also like -

Monday, 22 June 2015

Thread states in Java multithreading

It is important to know about the lifecycle of a thread and various states a thread can be in. That will give an idea about what happens after calling the start() method on a thread and how it is scheduled to run.

As we have already seen in a post about creating a thread that a thread can be created by extending Thread class or implementing Runnable interface, in both cases we need to provide implementation of the run() method. In order to begin execution of the run() method we need to call the start() method on the thread. That is when Java Virtual Machine calls the run method of the thread.

Once scheduled to run by JVM a thread will run when its gets CPU cycle, a thread may be in waiting, blocked or running state after scheduled to run and later transitions to terminated state. Let's see the states a thread can be in.

New

When a thread is created either by extending Thread class or implementing Runnable interface it is in "New State".

Thread thread1 = new ThreadDemoClass();

When a thread is in "New" state it is not yet scheduled to run.

Runnable

When we call start() method on the thread object that causes the thread to begin execution and it's the Java Virtual Machine that calls the run method of the thread.

Thread thread1 = new ThreadDemoClass();
thread1.start();

This state is called Runnable as thread may not start running as soon as the start() method is called. It depends on the native OS when it schedule the thread to start running. A thread starts running when it gets the CPU cycle. A running thread may change state to waiting, blocked, runnable again and terminated.

Blocked

When a resource is shared among various threads then a thread may go into blocked state as the resource may be used by another thread. In that case a thread has to suspend its execution because it is waiting to acquire a lock.
As exp. In case of synchronized block where only one thread can enter that block of code.

synchronized (object reference) {   
  //code that uses shared resource 
}  

A thread may also be blocked when it is blocking on I/O As exp. when a thread invokes a read() or write() method on I/O stream, that thread is blocked until there is some data to read, or the data is fully written.

Waiting

A thread that is waiting indefinitely for another thread to perform a particular action is in the waiting state.
As exp. A thread is waiting because of a call to wait() or join() method where no time of waiting is specified as parameter.

Example with Join

public final void join() throws InterruptedException

Timed_Waiting

A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
As exp. A thread is waiting because of a call to wait() or join() method where time of waiting is specified as parameter. Calling sleep(long millis) will also result in a thread entering a TIMED_WAITING state.

Example with Join

Using join() method with a parameter where time of waiting is specified in milliseconds.

public final void join(long millis) throws InterruptedException
rather than Using join() without any parameter
public final void join() throws InterruptedException

Example with Sleep

Thread myThread = new MyThreadClass();
myThread.start();
try {
    myThread.sleep(10000);
} catch (InterruptedException e){
 
}

Terminated

A thread that has exited is in this state. This happens when the thread has completed executing the run() method. A thread may also be terminated any time by calling its stop() method (note that Thread.stop() is deprecated and it is inherently unsafe)

thread states in java multithreading
Various thread states

That's all for this topic Thread states in Java multithreading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference between Thread and Process in Java
  2. What if run() method called directly instead of start() method
  3. Can we start the same thread twice in Java
  4. Thread priorities in Java multithreading
  5. Why wait(), notify() and notifyAll() methods are in Object class
  6. Java Multi-threading interview questions

You may also like -

Friday, 19 June 2015

What if run() method called directly instead of start() method - Java Multithreading

When we call start() method on the thread that causes this thread to begin execution and it’s the Java Virtual Machine that calls the run method of this thread.

If we directly call run method it will be treated as a normal overridden method of the thread class (or runnable interface). This run method will be executed with in the context of the current thread not in a new thread.

It’s the start() method that spawns a new thread and schedules the thread with the JVM. The JVM will let the newly spawned thread execute run() method when the resources and CPU are ready. So not calling the start method will mean a new thread object is not created and run() method will run as a normal overridden method.

As exp. - Let’s create a class and spawn two threads and cause some delay in the execution if they are real threads then there will be context switchingwhile one thread is not executing another thread will execute. When start method is not called no new threads are created thus there won’t be any context switching.

public class MyThreadClass extends Thread{
    @Override
    public void run(){
        System.out.println("In run method " + Thread.currentThread().getName());
        for(int i = 0; i < 5 ; i++){
            System.out.println("i - " + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        MyThreadClass mc1 = new MyThreadClass(“MyThread1”);
        MyThreadClass mc2 = new MyThreadClass();
        mc1.run();
        mc2.run();
    }
}

Output

In run method main
i - 0
i - 1
i - 2
i - 3
i - 4
In run method main
i - 0
i - 1
i - 2
i - 3
i - 4

As you can see in the above program that there is no context-switching because here t1 and t2 will be treated as normal object not thread object. Also name of the thread is not printed.

Now lets see the same program with start method.

public class MyThreadClass extends Thread{
    @Override
    public void run(){
        System.out.println("In run method " + Thread.currentThread().getName());
        for(int i = 0; i < 5 ; i++){
            System.out.println("i - " + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        MyThreadClass mc1 = new MyThreadClass();
        MyThreadClass mc2 = new MyThreadClass();
        mc1.start();
        mc2.start();;
    }
}

Output

In run method Thread-0
i - 0
In run method Thread-1
i - 0
i - 1
i - 1
i - 2
i - 2
i - 3
i - 3
i - 4
i – 4

Now you can see how context switching is happening and values are printed for both threads concurrently. You can even see the thread name printed now.

That's all for this topic What if we call run() method directly instead of start() method. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference between Thread and Process in Java
  2. Creating thread in Java
  3. Can we start the same thread twice in Java
  4. Deadlock in Java multi-threading
  5. Thread states in Java multithreading
  6. Thread priorities in Java multithreading
  7. Java Multi-threading interview questions

You may also like -

Thursday, 18 June 2015

fail-fast Vs fail-safe iterator in Java

Difference between fail-fast iterator and fail-safe iterator, apart from being an important Java Collections interview questions, is a very important concept to know. The collections which are there from Java 1.2 (or even legacy) like ArrayList, Vector, HashSet all have fail-fast iterator whereas Concurrent collections added in Java 1.5 like ConcurrrentHashMap, CopyOnWriteArrayList, CopyOnWriteArraySet have fail-safe iterator.

So first let us see the key differences between the fail-fast and fail-safe iterator and then we'll see some programs to explain those features.

  1. fail-fast iterator throws ConcurrentModificationException if the underlying collection is structurally modified in any way except through the iterator's own remove or add methods.
    fail-safe iterator doesn't throw ConcurrentModificationException.
  2. fail-fast iterator work on the original collection.
    fail-safe iterator makes a copy of the underlying structure and iteration is done over that snapshot. Drawback of using a copy of the collection rather than original collection is that the iterator will not reflect additions, removals, or changes to the collection since the iterator was created.
  3. fail-fast iterator provides remove, set, and add operations. Note that not all the iterators support all these methods. As exp. ListIterator supports add() method but the general iterator doesn't.
    With fail-safe iterator element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

Now let us see some detailed explanation and supporting programs to see these features of both fail-fast and fail-safe iterators.

fail-fast iterator in Java

An iterator is considered fail-fast if it throws a ConcurrentModificationException under either of the following two conditions:

  • In multi-threaded environment, if one thread is trying to modify a Collection while another thread is iterating over it.
  • Even with single thread, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

fail-fast iterator fails if the underlying collection is structurally modified at any time after the iterator is created, thus the iterator will throw a ConcurrentModificationException if the underlying collection is structurally modified in any way except through the iterator's own remove or add (if applicable as in list-iterator) methods.

Note that structural modification is any operation that adds or deletes one or more elements; merely setting the value of an element (in case of list) or changing the value associated with an existing key (in case of map) is not a structural modification.

Mostly Iterators from java.util package throw ConcurrentModificationException if collection was modified by collection's methods (add / remove) while iterating

Also note that according to Oracle Docs fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

Example code of fail-fast iterator with an attempt to add new value to a map while the map is being iterated

public class FailFastModification {
    public static void main(String[] args) {
        // creating map
        Map <String,String> cityMap = new HashMap<String,String>();
        cityMap.put("1","New York City" );
        cityMap.put("2", "New Delhi");
        cityMap.put("3", "Newark");
        cityMap.put("4", "Newport");
        // getting iterator
        Iterator <String> itr = cityMap.keySet().iterator();
        while (itr.hasNext()){
            System.out.println(cityMap.get(itr.next()));
            // trying to add new value to a map while iterating it
            cityMap.put("5", "New City");
        }        
    }

}

OUTPUT

New York City
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextNode(Unknown Source)
 at java.util.HashMap$KeyIterator.next(Unknown Source)
 at org.netjs.examples.FailFastModification.main(FailFastModification.java:20)

Though we can update the underlying collection, let's see an example with the same hash map used above -

public class FailFastModification {
    public static void main(String[] args) {
        // creating map
        Map <String,String> cityMap = new HashMap<String,String>();
        cityMap.put("1","New York City" );
        cityMap.put("2", "New Delhi");
        cityMap.put("3", "Newark");
        cityMap.put("4", "Newport");
        // getting iterator
        Iterator <String> itr = cityMap.keySet().iterator();
        while (itr.hasNext()){
            System.out.println(cityMap.get(itr.next()));
            // updating existing value while iterating
            cityMap.put("3", "New City");
        }        
    }
}

Here I have changed the value for the key "3", which is reflected in the output and no exception is thrown.

New York City
New Delhi
New City
Newport

Using iterator remove method I can remove the values, that is permitted.

public class FailFastModification {
    public static void main(String[] args) {
        Map <String,String> cityMap = new HashMap<String,String>();
        cityMap.put("1","New York City" );
        cityMap.put("2", "New Delhi");
        cityMap.put("3", "Newark");
        cityMap.put("4", "Newport");
        System.out.println("size before iteration " + cityMap.size());
        Iterator <String> itr = cityMap.keySet().iterator();
        while (itr.hasNext()){
            System.out.println(cityMap.get(itr.next()));
            // removing value using iterator remove method
            itr.remove();
        }
        System.out.println("size after iteration " + cityMap.size());        
    }
}

Output

size before iteration 4
New York City
New Delhi
Newark
Newport
size after iteration 0

Here after iteration the value is removed using the remove method of the iteartor, thus the size becomes zero after the iteration is done.

Let’s see a multi-threaded example, where concurrency is simulated using sleep method.

public class FailFastTest {
 public static void main(String[] args) { 
  final Map<String,String> cityMap = new HashMap<String,String>();
  cityMap.put("1","New York City" );
  cityMap.put("2", "New Delhi");
  cityMap.put("3", "Newark");
  cityMap.put("4", "Newport");
  //This thread will print the map values
  // Thread1 starts 
  Thread thread1 = new Thread(){ 
   public void run(){ 
    try{ 
     Iterator i = cityMap.keySet().iterator(); 
     while (i.hasNext()){ 
      System.out.println(i.next()); 
      // Using sleep to simulate concurrency
      Thread.sleep(1000); 
     }  
    }catch(ConcurrentModificationException e){ 
     System.out.println("thread1 : Concurrent modification detected on this map"); 
    }catch(InterruptedException e){
     
    } 
   } 
  }; 
  thread1.start(); 
  // Thread1 ends
   // This thread will try to remove value from the collection,
  // while the collection is iterated by another thread.
  // thread2 starts
  Thread thread2 = new Thread(){ 
   public void run(){ 
     try{ 
    // Using sleep to simulate concurrency
      Thread.sleep(2000);
      // removing value from the map
      cityMap.remove("2"); 
      System.out.println("city with key 2 removed successfully"); 
     }catch(ConcurrentModificationException e){ 
      System.out.println("thread2 : Concurrent modification detected on this map"); 
     } catch(InterruptedException e){}
    } 
  }; 
  thread2.start(); 
// thread2 end
 } // main end
} // class end

Output

1
2
city with key 2 removed successfully
thread1 : Concurrent modification detected on this map

It can be seen that in thread 1 which is iterating the map, Concurrent modification exception is thrown.

If we use the same multi-threaded program for updating the values, it should update the values.

public class FailFastTest {
 public static void main(String[] args) { 
  final Map<String,String> cityMap = new HashMap<String,String>();
  cityMap.put("1","New York City" );
  cityMap.put("2", "New Delhi");
  cityMap.put("3", "Newark");
  cityMap.put("4", "Newport");
  //This thread will print the map values
  Thread thread1 = new Thread(){ 
   public void run(){ 
    try{ 
     Iterator i = cityMap.keySet().iterator(); 
     while (i.hasNext()){ 
      System.out.println(cityMap.get(i.next())); 
      // Using sleep to simulate concurrency
      Thread.sleep(1000); 
     }  
    }catch(ConcurrentModificationException e){ 
     System.out.println("thread1 : Concurrent modification detected on this map"); 
    }catch(InterruptedException e){
     
    } 
   } 
  }; 
  thread1.start(); 
  
  Thread thread2 = new Thread(){ 
   public void run(){ 
     try{ 
    // Using sleep to simulate concurrency
      Thread.sleep(500);
      // removing value from the map
      cityMap.put("2", "New City"); 
      System.out.println("city with key 2 updated successfully"); 
     }catch(ConcurrentModificationException e){ 
      System.out.println("thread2 : Concurrent modification detected on this map"); 
     } catch(InterruptedException e){}
    } 
  }; 
  thread2.start(); 
 } // main end
} // class end

Output

New York City
city with key 2 updated successfully
New City
Newark
Newport

It can be seen while one thread is iterating through the map another thread is updating one of the value but that doesn't result in concurrentmodificationException.

Fail Safe iterator

In case of fail-safe iterator, ConcurrentModificationException is not thrown as the fail-safe iterator makes a copy of the underlying structure and iteration is done over that snapshot.
Since iteration is done over a copy of the collection so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.

Drawback of using a copy of the collection rather than original collection is that the iterator will not reflect additions, removals, or changes to the collection since the iterator was created. Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

Iterator of CopyOnWriteArrayList is an example of fail-safe Iterator also iterator provided by ConcurrentHashMap keySet is fail-safe and never throws ConcurrentModificationException.

Example code with fail-safe

public class FailSafeTest {
 public static void main(String[] args) {

  List <String> cityList = new CopyOnWriteArrayList<String>();
  cityList.add("New York City");
  cityList.add("New Delhi");
  cityList.add("Newark");
  cityList.add("Newport");  
  Iterator<String> itr = cityList.iterator();
  while (itr.hasNext())
         {         
          System.out.println(itr.next());
          cityList.add("NewCity");
          //itr.remove();
         }
 }
}

This program won't throw ConcurrentModificationException as iterator used with CopyOnWriteArrayList is fail-safe iterator.

If we uncomment the line //itr.remove(); this program will throw UnsupportedOperationException as fail-safe iterator does not support remove, set, and add operations.

Points to note -

  • An iterator is considered fail-fast if it throws a ConcurrentModificationException in case the underlying collection's structure is modified.
  • While iterating a list or a map values can be updated, only if an attempt is made to add or remove from the collection ConcurrentModificationException will be thrown by fail-fast iterator.
  • Fail-fast iterators throw ConcurrentModificationException on a best-effort basis and fail-fast behavior of an iterator cannot be guaranteed.
  • fail-safe iterator works with a copy of the collection rather than the original collection thus interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.
  • remove, set, and add operations are not supported with fail-safe iterator.

Related Topics

  1. ConcurrentHashMap in Java
  2. CopyOnWriteArrayList in Java
  3. How to loop/iterate an arraylist in Java
  4. ListIterator in Java
  5. How HashMap internally works in Java
  6. Java Collections interview questions

You may also like -