Home > Java certifications > Java thread tutorial

Java thread tutorial

j_thread_locksIf you are a newbie to working with java threads, this post will help you. Certifications like the SCJP require you to understand java threads to a fair degree. Threads behavior can be difficult to understand even for experienced programmers, so I will try to present some examples which will help candidates identify how threads wait / lock and synchronize.

Lets cut the chit chat and jump into a problem. A program increments a counter in a for loop as shown below.

Synchronizing:

public class StaticSync
{
    public static final Object s_lock = new Object();
    public static int s_counter=0;
    public static void main(String... args)
    {
        new StaticSync().go();
    }
 
    public void go()
    {
        for(int iCounter=0; iCounter<50; iCounter++)
        {
            Thread thread = new Thread(new Incrementer(new StaticSync()));
            thread.start();
        }
    }
}
 
class Incrementer implements Runnable
{
    StaticSync m_staticSync=null;
    public Incrementer(StaticSync staticSync_INP)
    {
        m_staticSync = staticSync_INP;
    }
 
    public void run()
    {
        synchronized (m_staticSync.s_lock)
        {
            m_staticSync.s_counter++;
            System.out.println(m_staticSync.s_counter);
        }
    }
}

This program is pretty simple. This is the sort of code that you can expect on the SCJP exam. Advanced versions of the code above can also appear by adding notify() wait() sleep() etc into the picture. Let us concentrate on the program for now. What can be guaranteed about the output of this program ?

Can we say that Numbers 1 through 50 will be printed for sure ? What can be said about the order in which they are printed. Is there a guarantee about that ?

This program prints numbers 1 through 50 and does it consistently. What that means is that we can guarantee that this program will print 1->50 in ascending order. Why ?

Instances of a thread object lock on the same static object:

j_thread_static_object_lock_1

One thread manages to obtain a lock. The others wait:

j_thread_static_object_lock_2

We are creating a new Incrementer instance while starting each thread. We are also passing it a new StaticSync instance for every thread. However when the code tries to update the counter, it synchronizes over a static object. The static object has only one instance, so when one of the 50 thread instances holds this lock, the other thread will have to wait until the lock is released.

Once the lock is released the next thread will update the counter variable. Since only one thread can obtain the lock at any given time, the operation of incrementing the counter and printing its value is atomic. What that means is that the ++ operation and the System.out.println() operation will happen without any other thread intefering in the middle. It happens as one single unit. Note that m_staticSync.s_lock is actually referring to the public static variable through a non static reference. This is not a recommended practice but it was used anyway to help readers understand the concept. The code also throws encapsulation out the window. Our focus is on the thread behavior of the code alone.

Now let us replace synchronized (m_staticSync.s_lock) with synchronized (this). What do you think will change (if there is any) and why ? What does “this” refer to here and how is the locking different from the locking we did in the first example ? If the program is modified so that we synchronize over a static method, which Object’s lock do we obtain ?

I will leave these questions to you as an exercise. The images below should provide a hint.

Threads locking on distinct object instances:

j_thread_nonstatic_object_lock_1

Everyone is a winner:

j_thread_nonstatic_object_lock_2

Moving on to thread interruptions

Interrupting:

public class ThreadInterrupt
{
 
    public static void main(String... args) throws Exception
    {
        new ThreadInterrupt().go();
    }
 
    public void go() throws Exception
    {
        InterruptTest interruptTest = new InterruptTest();
        Thread thread = new Thread(interruptTest);
        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
        Thread.sleep(1000);
    }
 
}
 
class InterruptTest implements Runnable
{
    public void run()
    {
        try
        {
            synchronized (this)
            {
                System.out.println("Waiting");
                wait(30000);
            }
        }
        catch (InterruptedException e)
        {
            System.out.println("Inerrupted");
        }
    }
}

This class shows you how interruption of threads work. When a thread waits or sleeps, it goes into a blocking state. Such threads can be interrupted to come out of the blocking state. When such a thread gets “interrupted” from its blocking state, it throws an InterrutpedException. The output of the program above is

Waiting
Inerrupted

I have never used the interrupt() method at work. But it is useful to know that this can be done. Just remember that only threads that are blocking can be interrupted. Trying to interrupt threads in the running state will not work.

Notification:

public class NotificationExample
{
    public static Object lock = new Object();
    public static void main(String... args)
    {
        new NotificationExample().go();
    }
 
    public void go()
    {
        for(int iCounter=0; iCounter&lt;100 ; iCounter++)
        {
            Thread thread = new Thread(new ThreadWorker());
            thread.start();
        }
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        synchronized (lock)
        {
            lock.notifyAll();
        }
    }
}
 
class ThreadWorker implements Runnable
{
    public void run()
    {
        synchronized (NotificationExample.lock)
        {
            try
            {
                NotificationExample.lock.wait();
                System.out.println(Thread.currentThread().getName() + " finished waiting");
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}

The SCJP exam expects you to understand how waiting and notifications happen in Threads. In this example, several threads synchronize over the same lock and then wait. A few seconds later a notifyAll() call is made to notify all the threads that were waiting on this Object’s lock. As an exercise, try to change the notifyAll() call to notify(). Observe what change that does to the execution of this program.

Some of the code displayed above uses the sleep() method to better explain and understand Thread behaviour when you run the examples. However making a Thread sleep does not guarantee any given result. You need to keep that in mind. The scenarios may also play out differently when you remove the calls to sleep(). What would happen for example if the notify() method is called before the threads actually begin waiting ?

You can toy around with those three examples to get a better grasp on threads.

Categories: Java certifications Tags: , ,
  1. Bhavya
    February 3rd, 2010 at 18:47 | #1

    A very good stuff…. made me to understand Thread concept in a better way.

  2. Javin Paul
    January 6th, 2011 at 13:03 | #2

    Nice article man , diagrams are really good to explain confusing threading concept to new comer. keep it up. you could have probably included deadlock in java as well.

    Thanks
    Javin

  3. February 6th, 2011 at 16:11 | #3

    Well explained article :)

  1. No trackbacks yet.