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
Runnableinterface over theThreadclass.