Threads in Java can be created two ways:
- Extending Thread Class
- Implementing Runnable Interface
Extending Thread Class:
class MyThread extends Thread{
/*
This is where your implementation of what happens when you start a thread goes.
You need to override the run method from the Thread class.
*/
@Override
public void run()
{
System.out.println("Thread is running");
}
}
class CreatingThreads {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
Implementing Runnable Interface
class MyRunnable implements Runnable{
@Override
public void run()
{
System.out.println("Thread is running");
}
}
class CreatingThreads{
public static void main(String[] args){
Runnable myRunnable = new MyRunnable();
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}
Using the Runnable
interface, you can also create threads via lambda expressions. The Thread class takes a Runnable
object, and the Runnable
interface has just one method run which takes no arguments. So, you can create a Thread
using the following pattern which is much easier to implement.
class CreatingThreads{
public static void main(String[] args){
Thread myThread2 = new Thread(() -> {
//do something here
//what do you want your thread to do
});
myThread2.start();
}
}
The advantage of implementing the Runnable
interface over extending Thread
class is that you'll have space to extend another class if required. (You can only extend one class in Java).
The other advantage is that each thread created by the Thread
class is associated with a new object whereas each thread created by the Runnable
interface shares the same object.
Let's look at the following code:
class MyRunnable implements Runnable{
public int number = 0;
@Override
public void run() {
number++;
System.out.println("Thread is running, "+number);
}
}
class MyThread extends Thread{
public int number = 0;
@Override
public void run() {
number++;
System.out.println("Thread is running, "+number);
}
}
class CreatingThreads{
public static void main(String[] args) throws InterruptedException {
System.out.println("Implementing Runnable Interface: ");
Runnable myRunnable = new MyRunnable();
Thread myThread = new Thread(myRunnable);
Thread myThread2 = new Thread(myRunnable);
myThread.start();
Thread.sleep(2000);
myThread2.start();
Thread.sleep(2000);
System.out.println();
System.out.println("Extending Thread Class: ");
MyThread secondMyThread = new MyThread();
MyThread secondMyThread2 = new MyThread();
secondMyThread.start();
Thread.sleep(2000);
secondMyThread2.start();
}
}
Output:
Implementing Runnable Interface:
Thread is running, 1
Thread is running, 2
Extending Thread Class:
Thread is running, 1
Thread is running, 1
As you can see threads created by implementing the Runnable
interface are acting on the same object whereas the ones created by extending the Thread
class are acting on different objects.
You can also find this on my blog: Oshan Upreti.
Top comments (2)
Well, the reason why in your last example the runnable threads are operating on the same object is because you only have instantiated one object, but you're using it in both threads:
If you want independent objects in your threads you can do that with runnable as well:
That's absolutely right. Thank you for your observation.
The point I wanted to prove here was that we can't create threads extending the Thread class that operates on the same object. And, that's the advantage of using the
Runnable
interface over theThread
class.