1. Extending the thread interface, is like you are making your class to behave as a thread only. You new class will be like a enhanced thread.
jshell> public class Test extends Thread{
...> public Test(String name){
...> super(name);
...> }
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> }
| created class Test
jshell> Test t1=new Test("MyThread");
t1 ==> Thread[MyThread,5,main]
It creates a thread, not the Test object. So it is gonna act like a single thread. You can not share the instance of Test class between threads.
2. Implementing the runnable interface.
jshell> public class Test1 implements Runnable{
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> public String getName(){
...> return "testing";}
...> }
| created class Test1
jshell> Test1 t1=new Test1();
t1 ==> Test1@396a51ab --> this creates Test1 object.
This object can be shared across threads by ,
jshell> Thread t1=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
jshell> Thread t=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
I think already lot have been discussed on this topic. though this might be helpfull in basics.