View RSS Feed

Thread

Using threads in Java applications

Rate this Entry
by , 04-03-2012 at 11:57 AM (5416 Views)
Are you going to code a Java application that processes multiple tasks at the same time? Or is your program doing some heavy operations in the background, while the user is viewing a chart report? Such applications are referred as multi-threaded or concurrency programs. The Java platform has built-in support for threading from its very early versions, so developing multi-threaded applications in Java is not tough at all, thanks to the comprehensive and powerful threading and concurrency API.

This article will walk you from fundamental concepts of thread to apply the API for Java applications that need multi-threaded capability.


What is a thread?

A thread is a flow of execution within a program. It is perhaps, the smallest unit of execution, beside process Ė an execution unit of a program. Generally, a program may consist of many processes, and each process may be divided into multiple threads.
The execution of any program always runs in a thread at least, whether you notice or not. For example, in Java, the main() method is always executed by a thread; a web server processes a userís request in a separate thread, etc. Many threads may be executed simultaneously within a program.

So, threads always exist in a running program, even you have never created one explicitly.


Benefit of using threads

Multi-threaded applications have many advantages, here to name a few:

  • For desktop applications, multi-threads keep the user interface responsive while doing some lengthy tasks in the background.
  • A server application can serve many usersí requests at the same time.
  • For batch processing programs, multi-threads help reducing processing time and increasing productivity.


However, while developing multi-threaded applications, developer should take care of synchronization of resources which are shared among threads to avoid inconsistent state of data, dead-locking, Ö


Java API for threads

To work with threads, you should be familiar with the Thread class and the Runnable interface. They are the core class and interface which reside in the java.lang package. Though the Java platform deserves a separate package for concurrency, java.util.concurrent, it is broader than scope of this article.

The Runnable interface

This interface defines a requirement for implementing objects that wish to execute code in a separate thread. It defines only one method, run(), which must be overridden by sub classes. Any code can be placed inside the run() method, and the Java Virtual Machine will call this method when it executes the thread.


The Thread class

This is the core class that represents a thread of execution in a Java program, it implements the Runnable interface. Your code must be placed inside (or call from) its run() method in order to be executed in a separate thread. The class has many constructors, however following are the three commonly used ones:

  • Thread(): this no-argument constructor simply creates a new Thread object with all defaults.
  • Thread(String name): creates new Thread object with the given name.
  • Thread(Runnable target): creates a new Thread object which wraps a Runnable object.



Some important methods are:

  • run(): this is the most important method, subclasses must override this method and code inside this method will be executed in a thread.
  • start(): starts execution of the thread, the run() method will be called.
  • sleep(long millis): causes current thread to be paused temporarily for a specified time in milliseconds. This is a static method.
  • join(): causes the calling thread waits for this thread to finish execution.
  • interrupt(): wakes up this thread if it is sleeping or waiting, an InterruptedException will be thrown.



Life cycle of a thread

Typically, a thread can be in one of the following states:

Name:  thread life cycle.png
Views: 2554
Size:  5.6 KB
Figure: Life cycle of a thread

  • New: when an instance of a Thread is created and it has not been started yet.
  • Runnable: when the start() method has been called, and the run() method has not been executed. Itís up for the JVM to decide when to call run() method, even when the start() method is called.
  • Running: when the run() method is called and being executed.
  • Waiting/Blocking: when the thread is going to sleep while running or it has to wait for a resource available to continue. The thread will become runnable when it exits the waiting/blocking state.
  • Dead: the thread become dead when the run() method completes. A dead thread cannot be started over again.


Creating a thread

There are two methods to create a thread: by subclassing the Thread class, or by implementing Runnable interface.

The first method: Create a new class that extends Thread class, and override run() method:

Java Code: Extending Thread class
public class DemoThread extends Thread {
        public void run() {
            // code executed in thread placed here...
        }

}

Thread thread = new DemoThread();

The second method: Create a new class that implements Runnable interface, and implement run() method:

Java Code: Implementing Runnable interface
public class DemoThread implements Runnable {
        public void run() {
            // code executed in thread placed here...
        }

}
    Runnable runnable = new DemoThread();
    Thread thread = new Thread(runnable);
So, whatís difference? Well, itís all about flexibility. With the first method, the implementing class can change behavior of the Thread class, such as providing custom implementation for some methods, or creating a wrapper class. However, the implementing class will not be able to extend another class (because Java does not allow multiple inheritances). With the second one, you are free to let your class extends another class while still keeping behavior of a thread. Itís up to you to decide which method to follow, however the latter method is preferred in practice, since itís more flexible.


Starting a thread

Just call the start() method of the Thread class:

Java Code: Start a thread
thread.start();
Then the JVM will call run() method and execute the code inside run() method in a separate thread. When the run() method completes, the thread become die. If the start() method is invoked again, an IllegalThreadStateException will be thrown.


Using sleep(), join() and interrupt()

The following code snippet demonstrates using of sleep() method. The current thread pauses for 10 seconds for each loop:

Java Code: Using sleep() method
public class DemoThread extends Thread {
    public void run() {
        while (true) {
           
            // do something here...
           
            try {
                Thread.sleep(10000);    // sleep for 10 seconds
            } catch (InterruptedException ex) {
                // interrupted, exits sleep state
            }
        }
    }
   
}
The sleep() method is static, so calling it will affect the currently running thread. The exception InterruptedException is thrown when this thread is interrupted when the interrupt() method is invoked on this thread object.

When the join() method is invoked on a thread, the calling thread will wait for the called thread to finish. In the following example, the main thread (the thread that executes the main() method) will wait for the thread thread1 to finish, then the main thread continue its execution:

Java Code: Using join()
public class DemoThread extends Thread {
    public void run() {
        while (true) {
           
            // do something here...
           
            try {
                Thread.sleep(10000);    // sleep for 10 seconds
            } catch (InterruptedException ex) {
                // interrupted, exits sleep state
            }
        }
    }
   
    public static void main(String... args) {
        Thread thread = new DemoThread();
        System.out.println("It's the thread's turn");
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException ex) {
            // interrupted while waiting
        }
        System.out.println("It's my turn");
    }
}
So when does join() need to be called? Well, when the calling thread needs to process something done by the called thread, so it has to wait for the called thread done processing. Otherwise, if not using join(), the calling thread is still running in parallel with the called thread, so it my access the data in wrong state.

The interrupt() method is often called to interrupt a currently sleeping/waiting thread. For example, in the following code, when the thread is sleeping, it will be woke up and exits the while loop if an interrupt() is called:

Java Code: Using sleep() method
    public void run() {
        while (true) {
           
            // do something here...
           
            try {
                Thread.sleep(10000);    // sleep for 10 seconds
            } catch (InterruptedException ex) {
                // interrupted, exits sleep state
            }
        }
    }
   
    // another thread interrupts

    thread.interrupt();

Calling interrupt() will thrown an InterruptedException to the sleeping/waiting thread. However, it does not have any effect for a running thread (not sleeping/waiting).


Synchronization issue

Problems might be occurred when multiple threads accessing a same object, such as inconsistent state of an object being modified/accessed by many threads concurrently. To address the problem, Java introduces synchronized keyword. When a method or a code block is marked with synchronized keyword, the method or code block can be accessed by only one thread at a time, thus eliminates the inconsistent state problem. Though this article is not focusing on synchronization topic, the synchronization issue should be taken care of when developing multi-threaded applications.


Threading in Swing

Javaís Swing framework is single-threaded, that means Swingís UI components can be accessed by only one thread at a time. A thread is called event dispatching thread, which is the only thread that can access Swing components. So the Java API provides the SwingUtilities class with two static methods which should be used when using multiple threads in Swing:

  • SwingUtilities.invokeLater(Runnable doRun): executes the code in the event dispatching thread, the method returns immediately.
  • SwingUtilities.invokeAndWait(Runnable doRun): executes the code in the event dispatching thread, but the method has to wait for the code to execute.



So remember to use those two methods when using threads in Swing applications.


Methods are no longer used

Some of the methods in Thread class are deprecated, so using them is greatly discouraged. These methods are: destroy(), resume(), stop(), suspend(). Consult the Java API documentation for more details.


Conclusion

The Java platform has built-in great support for threading, however there are some notices should be considered when developing multi-threaded applications: the synchronization issue, the Swingís single thread model, and the deprecated methods.

Submit "Using threads in Java applications" to Facebook Submit "Using threads in Java applications" to Digg Submit "Using threads in Java applications" to del.icio.us Submit "Using threads in Java applications" to StumbleUpon Submit "Using threads in Java applications" to Google

Tags: java, thread, tutorial Add / Edit Tags
Categories
Tutorial

Comments