What is thread?
A thread in Java is the smallest unit of execution within a program. It allows different parts of the program to run concurrently, enabling parallel processing and improving overall performance.
Threads in Java operate independently, sharing the same memory space and resources, but each with its own execution path.
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.
Threads differ from processes in that processes have their own memory space and resources, while threads share these resources within a process.
This makes threads more lightweight and efficient for multitasking and parallel computing.
How to create Thread ?
There are a couple of ways of creating a thread.
I. Extending Thread class
A new thread may be created by extending java.lang.Thread
class.
The class which extends Thread
should have run()
method defined in it.
It is the run()
method that 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:
- Create an object of the class implementing
java.lang.Runnable
. - Create an object of java.lang.Thread class or a class which extends it.
- 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 typejava.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
- A thread represents a task which is to be executed along with some other tasks.
- Whether a class representing a thread extends Thread class or implements
java.lang.Runnable
, it needs to have a run() method defined. - The signature of run method should be
public void run() { }
.
If a class implementsjava.lang.Runnable
or extendsjava.lang.Thread
and provides a run method with a different signature such aspublic int run (String thread) { }
, then it will be a compiler error. - Access modifier of
run
method should be public.
The reason behind this is simple.
We are implementingrun
method of an interface which is implicitly public and we cannot reduce the visibility of a method while implementing / overriding. - start() method is defined in
java.lang.Thread
class and not injava.lang.Runnable
interface. - run() method is defined in
java.lang.Runnable
interface. - You cannot call start() method directly on an instance of class which implements
java.lang.Runnable
while you can do this on class extendingjava.lang.Thread
. What this means ispublic 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 youThe method start() is undefined for the type MyClass
java.lang.Thread
class internally implementsjava.lang.Runnable
.- Starting java 8,
java.lang.Runnable
interface is afunctional interface
. An interface which has exactly one abstract method.