Why is not final? Why do you need to renew Thread?

I got this as an interview question.

Why is the Thread class not final? Why do you need to renew Thread ever?

I could not come up with examples of use in the real world.

+6
source share
6 answers

From Oracle Documentation :

There are two ways to create a new thread of execution. One of them is to declare the class a subclass of Thread. This subclass should override the run method of the Thread class. Another way to create a thread is to declare a class that implements the Runnable interface.

So the answer is: "you may want to subclass Thread override its run() method."

These paragraphs have been in the Java documentation since JDK 1.1. Java has added other convenient classes for controlling concurrency, primarily the executors mentioned in the comments, possibly reducing or eliminating the need for the Thread extension. However, they cannot make it final , because it will break compatibility.

For practical reasons, I think the only reason you would want to extend Thread rather than implement Runnable today would be to override its methods other than run() . For example, you can add registration or additional cleanup.

+9
source

This is pretty much just taken from John Wint's comment, but I think this is the best answer.

The only time I can think about where I could extend Thread instead of implementing Runnable - or, even better, just use ExecutorService with Future - is when I need to override Thread.interrupt() to do some cleanup. Otherwise, I see no practical reason for the actual extension of Thread .

+2
source

Two cases:

  • To create a new type of Thread , perhaps one that will clear some resource after completion, etc.
  • To override the run() method rather than providing a Runnable constructor (note: avoid this pattern - this is not the right approach)
+1
source

Another reason Thread not final is that in the early days of Java, overriding run() was considered a good design pattern. (I think in the days before anonymous classes this was considered "tidier" for a Thread subclass than for creating a free- Runnable class that implements Runnable .)

In any case, when Java 1.0 was released because it was impossible to fix the problem by changing Thread to final. This would break a lot of existing code.

+1
source

Let me say the following: when developing a language that is a tool like any other, you need to think in terms of pluses and minuses, and not just limit the tool, because we cannot see the real use cases that apply. By doing this, we can theoretically understand such decisions. Basically, the exercise asks another question.

Why should Thread be final?

Let me understand.


(I donโ€™t include the backward compatibility argument, I personally donโ€™t like it, because I think we should always focus on improving locally)

To discuss this issue, we need to understand the benefits of declaring a class as final or not.

Performance

Here TofuBeer said:

Virtual (overridden) methods are usually implemented through some kind of table (vtable), which ultimately is a pointer to a function. Each call method has the overhead associated with having to go through this pointer. when classes are marked final, then all methods cannot be overridden and the use of a table is no longer required - it's faster.

Some virtual machines (for example, HotSpot) can do something more reasonably and know when methods are not overridden and generate faster code as needed.

Security

The oracle is emphasized here :

Better to create security-friendly APIs. Attempting to modify security in an existing API is more complex and error prone. For example, creating a class final prevents a malicious subclass from adding finalizers, cloning, and overriding random methods.

There are also problems with invariants and confidential information . However, all security issues are project specific and not applicable to a tool that can be used in non-security scenarios.

Convenience

andersoj called this nice IBM article here :

final classes and methods can be significant inconvenience when programming - they limit your options for reusing existing code and expanding the functionality of existing classes. Sometimes a class is final for a good reason, for example, to ensure that the benefits of using the end results are respected, they must outweigh the inconvenience. Improving performance is almost always a bad reason to compromise on good object-oriented design principles, as well as improving performance with little or no effect, this is a bad compromise indeed.

So, from my point of view, if there is no strong benefit to setting the class as final, if the JVMs are able to do such performance optimizations, I would say that the gain is in a convenient argument.

Thus, we can extend the Thread class and do whatever we want with it, some initialization / finalization elements, such as logging, changing thread names, type of thread ... This is for you!

+1
source

These can be fields for storing local thread variables in the derived Thread class. Such variables may also be available when the run() methods are not overridden, and the thread executes Runnable , as usual. Such user threads can be controlled by the standard ExecutorService , creating them in a custom ThreadFactory and discarding them if necessary.

I also know that there is also ThreadLocal , but if the fields require cleaning (let's say it's a database connection), this can be pretty elegantly done by calling super.run() to process Runnable and completing the finalization just before run returns the method (therefore stream ends).

0
source

Source: https://habr.com/ru/post/914722/


All Articles