Basic of Thread

In concurrent programming, there are two basic units of execution: processes and threads. In the Java, concurrent programming is mostly concerned with threads.
Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process. Threads share the process’s resources, including memory and open files.

ITCuties - Java Thread

ITCuties – Java Thread

For instance, in word processor application many tasks are executed at the same time – responding to user, spelling checking, formatting and certain backgrounds tasks etc. These tasks are executed as a thread share word processor resources.

So what exactly is a thread?

  • An instance of class java.lang.Thread
  • A thread of execution

An instance of Thread is just an object. Like any other object in Java, it has variables and methods, and lives and dies on the heap
But a thread of execution is an individual process (a lightweight process) that has its own call stack. (a call stack is a stack data structure that stores information about the active subroutines of a computer program).

Even if you don’t create any new threads in your program, threads are back there running.
The main() method, that starts the whole thing, runs in one thread, called the main thread. But as soon as you create a new thread, a new stack materializes and methods called from that thread run in a call stack that’s separate from the main() call stack. That second new call stack is said to run concurrently with the main thread.

How to create threads

A Java thread can be created in two ways

  1. Extending java.lang.Thread
  2. Implementing java.lang.Runnable

Extending the Thread class

You’ll first consider how to extend the Thread class. You need to override the run() method when you want to extend the Thread class. If you don’t override the run() method, the default run() method from the Thread class will be called, which does nothing.

The simplest way to define code to run in a separate thread is to

  • Extend the java.lang.Thread class
  • Override the run() method.

To override the run() method, you need to declare it as public; it takes no arguments and has a void return type – in other words, it should be declared as public void run().
A thread can be created by invoking the start() method on the object of the Thread class. When the JVM schedules the thread, it will move the thread to a runnable state and then execute the run() method. When the run() method completes its execution and returns, the thread will terminate.

Example: MyThread.java

package com.javalatte.itcuties.basicofthread;

/**
 * How to create thread by extending thread class
 */
public class MyThread extends Thread {

    /**
     * Always override run() method of Thread class, otherwise default run()
     * method will run which does nothing
     */
    @Override
    public void run() {
        System.out.println("Welcome to itcuties.com");
        System.out.println("Thread name in run() : " + getName());
    }

    public static void main(String[] JavaLatte) {
        // thread creation
        Thread thread1 = new MyThread();
        //starting thread
        thread1.start();
        System.out.println("Thread name in main() : " + Thread.currentThread().getName());
    }
}

In this example, we’ll use getName() instance method of thread class to get the name of the thread. Because main() is a static method, you don’t have access to this reference. So you get the current thread name using the static method currentThread() in the Thread class.

Example: MyThreadWithoutRun.java

package com.javalatte.itcuties.basicofthread;

/**
 * This class demonstrate what would happen when we don't override run()
 */
public class MyThreadWithoutRun extends Thread {

    public static void main(String[] JavaLatte) {
        Thread thread1 = new MyThreadWithoutRun();
        thread1.start();
        // no output because we haven't declare anything to run as a output
    }
}

When we don’t override run() method. No output will come as we haven’t declare any task to be executed as a thread.

An important note: you do not invoke the run() method directly. Instead you start the thread using the start() method; the run() method is invoked automatically by the JVM.
The limitation with this approach is that if you extend Thread, you can’t extend anything else.

Implementing the Runnable interface

The Thread class itself implements the Runnable interface. Instead of extending the Thread class, you can implement the Runnable interface. The Runnable interface declares a single method, run().

//in java.lang package
public interface Runnable {
	public void run();
}

Implementing the Runnable interface gives you a way to extend any class you like, but still define behavior that will be run by a separate thread
When you implement the Runnable interface, you need to define the run() method. But Runnable does not have start() method. So, how do you create a thread if you implement the Runnable interface? Thread has an overloaded constructor, which takes a Runnable object as an argument – Thread(Runnable target)
You can use this constructor to create thread from a class that implements Runnable interface.

Example: MyRunnable.java

package com.javalatte.itcuties.basicofthread;

/**
 * How to implement Runnable Interface to create thread
 */
public class MyRunnable implements Runnable {

    public void run() {
        System.out.println("Welcome to itcuties.com");
        System.out.println("Thread name in run() : " + Thread.currentThread().getName());
    }

    public static void main(String[] JavaLatte) {
        // thread creation
        Thread thread1 = new Thread(new MyRunnable());
        //starting thread
        thread1.start();
        System.out.println("Thread name in main() : " + Thread.currentThread().getName());
    }
}

Besides the no-arg constructor and the constructor that takes a Runnable there are other overloaded constructors in class Thread. The constructors we care about are:

  • Thread()
  • Thread(Runnable target)
  • Thread(Runnable target, String name)
  • Thread(String name)

Example: ThreadConstructor.java shows how to set the name of the threads.

package com.javalatte.itcuties.basicofthread;

/**
 * How to use Thread(Runnable target, String name) constructor
 */
class Task implements Runnable {

    public void run() {
        System.out.println("Runnable Task is executed here");
        System.out.println("Name of this Runnable thread : " + Thread.currentThread().getName());
    }

}

public class ThreadConstructor {

    public static void main(String[] JavaLatte) {
        Thread thread1 = new Thread(new Task(), "RunnableTask");
        thread1.start();
    }
}

Remember, every thread of execution begins as an instance of class Thread. Regardless of whether your run() method is in a Thread subclass or a Runnable implementation class, you still need a Thread object to do the work.

How to start and run Multiple threads

In the above, we already have two thread, one is main() method stats in a thread of its own and thread.start() started a second thread.
In this example, we create a single Runnable instance and 3 Thread instances. All of these get the same Runnable instance and each thread will given a unique name.

Example: MultipleThread.java

package com.javalatte.itcuties.basicofthread;

/**
 * How to start and run multiple thread
 */
class PrintTask implements Runnable {

    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Print by " + Thread.currentThread().getName() + " : " + i);
        }
    }
}

public class MultipleThread {

    public static void main(String[] JavaLatte) {
        Thread t1 = new Thread(new PrintTask());
        t1.setName("Thread1");
        Thread t2 = new Thread(new PrintTask());
        t2.setName("Thread2");
        Thread t3 = new Thread(new PrintTask());
        t3.setName("Thread3");
        t1.start();
        t2.start();
        t3.start();
    }
}

When you run this code multiple time, each time you’ll get different order of the thread printing value because that there is nothing in the Java specification that says threads will start running in the order in which they were started. And there is no guarantee that once a thread starts executing, it will keep executing until it’s done. Each thread will start, and each thread will run to completion.

Point to remember is Once a thread has been started, it can never be started again. If you try to call start() a second time, it will cause an exception an IllegalThreadStateException. Only a new thread can be started, and then only once. A runnable thread or a dead thread cannot be restarted.

Choose between extend the Thead and implement the Runnable

When you are sure that you class is not going to extend any class other than Thread class, then you choose extending Thread class. Even you can use getName() method directly whereas you need to write Thread.currentThread().getName() while implementing Runnable interface.
There is limitation with the approach of extending Thread class that you can’t extend anything. So, implementing Runnable is a little convenient in this case.
Both the techniques are useful and mostly equivalent for problem solving.

Start() and Run() Methods

What we have seen is that we override the run() method but invoke the start() method. What will happen if you call run() method instead of start() method. Execute the following example and analyze the output.
Example : ThreadRunDemo.Java

package com.javalatte.itcuties.basicofthread;

/**
 * This show what will happen if you call run() instead of start() method
 */
class Task2 implements Runnable {

    public void run() {
        System.out.println("Thread name in run() : " + Thread.currentThread().getName());
    }
}

public class ThreadRunDemo {

    public static void main(String[] JavaLatte) {
        // thread creation
        Thread thread1 = new Thread(new Task2());
        //starting thread
        thread1.run();
        System.out.println("Thread name in main() : " + Thread.currentThread().getName());
    }
}

Sample Output:

Thread name in run() : main
Thread name in main() : main

If you call the run() method directly, it simply executes as part of the calling thread. It does not execute as a thread: it doesn’t get scheduled and get called by the JVM. That is why the getName() method in the run() method returns main instead of Thread-0.

Download this sample code here.

One Response to "Basic of Thread"

  1. Ashish Bhosle says:

    Very nice

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>