Why is it important to extends Thread Class In Java to create parameterised constructor

I am trying to understand what happen behind the scenes in Java Thread class - Here is the scenario

Scneario 1

I have main class like this

public class LoadBalancerUpStreamManagement extends Thread{

    public static void main(String args[]){

        LoadBalancerUpStreamManagement loadBalancerUpStreamManagement  = new LoadBalancerUpStreamManagement();
        loadBalancerUpStreamManagement.start();
        
    }
}

In the above scenario, as we have extended Thread class hence, its start method has also inherited. When we call the start method on object loadBalancerUpStreamManagement, it start and JVM internally called the run method on the new thread. Make sense so far.

Now consider another scenario

public class LoadBalancerUpStreamManagement extends Thread{

    public static void main(String args[]){
        
        LoadBalancer elb = new LoadBalancer();

        new Thread(elb);  ---> 2. It gives me constructor error - Can not resolve constructor Thread(LoadBalancer) 
    }
}

class LoadBalancer { ------> 1. I have not extended the Thread class here 


}


I am not able to understand, why is it important to extends Thread Class - Which OOPS concept is breaking and what is going on behind the scene?

If I extends Thread class then it all good.

public class LoadBalancerUpStreamManagement extends Thread{

    public static void main(String args[]){

        LoadBalancer elb = new LoadBalancer();
        new Thread(elb);  ------> 2. It is all good here. 
    }
}

class LoadBalancer extends Thread{ ---> 1. Extended Thread Class 


}



Solution 1:

Thread class has few constructors available, one of which is Runnable

Thread(Runnable target)

full list can be found here: https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html

Another important thing is that Thread class implements Runnable interface. Therefore whichever class extends Thread also gets to implement Runnable with the method run that you mentioned. That is why you can pass your classes that extended Thread in that constructor - because they are instanceof Runnable

Solution 2:

Look at the source code for class java.lang.Thread1.
It has a Runnable member.

/* What will be run. */
private Runnable target;

However this member may be null. Hence class Thread also implements Runnable

public class Thread implements Runnable

Now look at the code for method run in class Thread

public void run() {
    if (target != null) {
        target.run();
    }
}

If target is null, method run does nothing.
Therefore you have two options.

  1. Assign a value to member target – which can only be done via one of the constructors of class Thread2. Note that this value can be an instance of any class that implements Runnable. It does not have to be another class that extends Thread and, since Java 8, it can also be a lambda expression.
public class LoadBalancerUpStreamManagement extends Thread{
    public static void main(String args[]){
        LoadBalancer elb = new LoadBalancer();
        new Thread(elb);
    }
}

class LoadBalancer implements Runnable {
    public void run() {
        System.out.println("Replace with your code.");
    }
}

OR

public class LoadBalancerUpStreamManagement extends Thread{
    public static void main(String args[]){
        new Thread(() -> System.out.println("Replace with your code.")); // lambda expression
    }
}
  1. Write a class that extends Thread and overrides its run method (as you have done).

1 The source code is included in the JDK. Look for file src.zip under the directory where you installed the JDK.

2 Refer to javadoc for class Thread