What is thread?

A thread is a piece of task which is to be executed in parallel to another task executed by an application.
Example, Consider a text editor which performs auto save operation after some particular length of text is typed into it.
Now there are two tasks, first showing the text typed into the editor and second, performing auto save.

Since the two tasks should be executed in parallel, they are performed in different threads.
If both operations are done on the same thread, then while the thread is busy saving, it could not perform the typing process and it will show a lag till the save operation completes.

How to create Thread ?
There are a couple of ways of creating a thread.

I. Extending Thread class

Each thread is an instance of thread. So, a new thread may be created by extending java.lang.Thread class.
The class which extends Thread should have run() method defined in it.
run() method contains the task which is to be executed by the thread.
The new thread is started by calling start() method defined in Thread class.

Refer code below:

public class NewThread extends Thread { 
  public static void main(String[] args) { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName()+"\""); 
    NewThread thread = new NewThread (); 
    //start new thread thread.start(); 
  } 
 
  public void run() { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName()+"\""); 
  } 
}

Above code outputs:

This is thread: “main”
This is thread: “Thread-0”

II. Implementing Runnable
Another way of creating a new thread is by making a class implement Runnable.
Runnable is an interface in java.lang package which contains run method.
When you implement Runnable, you have to provide definition of run method in your class.
run method contains the task to be executed in a thread.

For starting a thread that implements java.lang.Runnable, follow below steps:

  1. Create an object of the class implementing java.lang.Runnable.
  2. Create an object of java.lang.Thread class or a class which extends it.
  3. Supply the object created in Step 1 to the constructor in Step 2. This is because constructor of java.lang.Thread class accepts an object of type java.lang.Runnable.

Example is given below:

public class NewTask implements Runnable { 
  public static void main(String[] args) { 
    System.out.println("This is thread:\"" + 
       Thread.currentThread().getName() + "\""); 
    /* create object of Thread with object 
     * of Runnable as argument */ 
    Thread ob = new Thread(new NewTask()); 
    ob.start(); 
  } 

  public void run() { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName()+"\""); 
  } 
}

Above code outputs:

This is thread: “main”
This is thread: “Thread-0”

Runnable as Lambda expression
Java 8 introduced the concept of Lambda expressions which simplifies the implementation of interface methods.
Now, there is no need to

  • Create a separate class that implements java.lang.Runnable,
  • Define run method in it,
  • Create an object of this class.

You can directly write the implementation of run method using Lambda expression where required as shown below.

public class NewTask { 
  public static void main(String[] args) { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName()+"\""); 
    // define Runnable as Lambda expression 
    Runnable r = () -> { 
      System.out.println("This is thread:\"" + 
       Thread.currentThread().getName() + "\""); 
    }; 
    Thread ob = new Thread(r); 
    ob.start(); 
  }
}

Note that the class does not implement java.lang.Runnable interface now.

A Lambda expression is created using a special syntax, you may refer this article to learn and understand Lambdas in detail.

With Lambda expression, the body of an interface method can be defined where it is required.
Above piece of code can be further reduced as

Thread ob = new Thread(
  () -> { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName() + "\""); 
  }); 
ob.start();

Moreover, it can be further reduced to a one-liner as

// create thread with runnable as Lambda expression 
Thread ob = new Thread(
  () -> { 
    System.out.println("This is thread:\"" + 
      Thread.currentThread().getName() + "\""); 
}).start();

Let’s tweak in

  1. A thread represents a task which is to be executed along with some other tasks.
  2. Whether a class representing a thread extends Thread class or implements java.lang.Runnable, it needs to have a run() method defined.
  3. The signature of run method should be public void run() { }.
    If a class implements java.lang.Runnable or extends java.lang.Thread and provides a run method with a different signature such as public int run (String thread) { }, then it will be a compiler error.
  4. Access modifier of run method should be public.
    The reason behind this is simple.
    We are implementing run method of an interface which is implicitly public and we cannot reduce the visibility of a method while implementing / overriding.
  5. start() method is defined in  java.lang.Thread class and not in java.lang.Runnable interface.
  6. run() method is defined in java.lang.Runnable interface.
  7. You cannot call start() method directly on an instance of class which implements java.lang.Runnable while you can do this on class extending java.lang.Thread. What this means is
    public class MyClass implements Runnable { 
      public static void main(String[] args) { 
        MyClass obj = new MyClass(); 
        obj.start(); 
        //compiler error here 
      } 
    }

    Trying to call start on an instance of class implementing `java.lang.Runnable` will give you

    The method start() is undefined for the type MyClass

  8. java.lang.Thread class internally implements java.lang.Runnable.
  9. Starting java 8, java.lang.Runnable interface is a functional interface. An interface which has exactly one abstract method.

Do not forget to hit the clap if the article was informative.

Leave a Reply