Why is Thread not an abstract class and start() not final?

JavaMultithreading

Java Problem Overview


Why was the Thread class implemented as a regular class and not an abstract class with run() method being abstract.

Will it possibly introduce any problems? Or does it have any use in being this way?

Also, the Thread.start() method is supposed to be a very specific method whose functionality cannot be implemented by any other class (If I am not wrong). And hence I guess the final keyword would be apt for this more than any other method.

But I am able to override this method and use it as I like,

public class Test extends Thread {
	public static void main (String... args) {
		Thread test = new Test();
		test.start();
	}
	
	@Override
	public void run() {
		System.out.println("New thread started...");
	}
	
	@Override
	public void start() {
		System.out.println("Did anyone tell you I will spawn a new thread??");
	}
}

It obviously only printed,

> Did anyone tell you I will spawn a new thread??

Is there any use in overriding other than confusing the engineer replacing you?

If not, why was the method not declared final in Thread class?

Java Solutions


Solution 1 - Java

You can of course choose to shoot yourself in the foot, but that doesn't mean you must.

> Why was the Thread class implemented as a regular class and not an abstract class with run() method being abstract.

Because the recommended way to create a start a thread is not to subclass Thread. The recommended way is to define a Runnable, and pass it as argument to the Thread constructor:

Runnable r = new Runnable() {
    @Override
    public void run() {
        ...
    }
};
Thread t = new Thread(r);
t.start();

> And hence I guess the final keyword would be apt for this more than any other method.

Yes and no. You can't replace the implementation of start() by your own implementation, but you can do additional things in start() if you want:

@Override
public void start() {
    System.out.println("Did anyone tell you I will spawn a new thread??");
    super.start();
}

That said, if Java was redesigned from scratch today, there is a good chance the design would be different. Remember that this class dates from Java 1.0, and is still backward-compatible.

Solution 2 - Java

> Why was the Thread class implemented as a regular class and not an > abstract class with run() method being abstract.

This question actually boils down to the fact that you should always prefer composition over inheritance.

If the Thread class was declared as abstract, the language would have to provide another class that extended from it which programmers could use to create a Thread. Your question would then be about why this class that extends from Thread is not abstract. If the language did not provide another class that extends from Thread, programmers would have to create their own class that extends from Thread and override the run() method.

> If not, why was the method not declared final in Thread class??

The only possible explanation I can give is that the developers of the language saw some use-cases for overriding start when the class was introduced to the JDK. The first version of Java that I used was 1.5 and I personally have not come across a use-case where I found the need to override start. As JB Nizet stated in his answer

> if Java was redesigned from scratch today, there is a good chance the design would be different

Solution 3 - Java

> Why is Thread.start() not final?

Are you sure you would never want to override it?

Class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r) {
            @Override
            public void start() {
                LOGGER.info("Starting thread " + this);
                super.start();
            }
        };
    }
}

Solution 4 - Java

I feel a few calirifcations should be posted for the answers :

> "Are you sure you would never want to override it?"

No ! I would not. Thats like saying, "Are you sure , you want to declare this variable private?" Because if I could declare any variable I use as public without fearing that other developers may mess my design logic, coding would be a breeze. One of the most important purpose of OOPS concepts of Scope, abstraction, polymorphism, Error handling etc is to communicate to other developers the design and intentions behind your code.As pointed out in the question, when you override start method, nobody is forcing you to use super.start(). @Codebender wrote a start method for a thread without using super.start() and compiler never complained. So he is free to break the whole mechanism of Threading and compiler is suppose to just let it pass? Thread's start method ensures that run method is called and execute at the right time ! It is critical to the very concept of Threading. I would be more than happy to be corrected, if I missed something here. 2.

> Because the recommended way to create a start a thread is not to > subclass Thread.

OK, if codebender is allowed by design, to sublass Thread and mess up the start method, By that logic, it is the design shooting itself in the foot. By another statement made,(which I agree with completely) , Runnable is the recommended way. Then why do we allow Thread class at all to instantiate the thread at all with no restrictions? This is followed by :
> You can't replace the implementation of start() by your own > implementation,

That actually supports codebender's claim that start method should be final when you say that.. ^

The one point, that's valid, is mentioned already as a side note, but is the actual answer to this question "Backward compatibility".

In fact, improvements were even going on as late as JDK 5.0 , when they incorporated many major additions and clarifications to the Java concurrency model. We want backward compatibility to be supported all the way and thats why Thread class is still exactly as it was before, even though Runnable interface is the recommended way nowadays.

Again, I would be more than happy to be corrected, if I missed something.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCodebenderView Question on Stackoverflow
Solution 1 - JavaJB NizetView Answer on Stackoverflow
Solution 2 - JavaChetan KingerView Answer on Stackoverflow
Solution 3 - JavaSolomon SlowView Answer on Stackoverflow
Solution 4 - Java Utkarsh SrivastavaView Answer on Stackoverflow