Dlaczego Thread
klasa została zaimplementowana jako zwykła klasa, a nie klasa abstrakcyjna z run()
metodą abstrakcyjną.
Czy może to spowodować jakieś problemy? A może ma to jakiś sens?
Ponadto Thread.start()
metoda ma być bardzo specyficzną metodą, której funkcjonalności nie może zaimplementować żadna inna klasa (jeśli się nie mylę). Dlatego myślę, że to final
słowo kluczowe byłoby bardziej odpowiednie do tego niż jakiejkolwiek innej metody.
Ale mogę zmienić tę metodę i używać jej tak, jak lubię,
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??");
}
}
To oczywiście tylko wydrukowane,
Czy ktoś ci powiedział, że utworzę nowy wątek?
Czy ma sens zastępowanie innych niż dezorientowanie zastępującego cię inżyniera?
Jeśli nie, dlaczego metoda nie została zadeklarowana jako ostateczna w klasie Thread?
java
multithreading
Codebender
źródło
źródło
Thread
zajęcia były ostateczne. Konstruktor już przyjmuje plik runnable, więc dziedziczenie nie jest potrzebne do utworzenia wątku.Odpowiedzi:
To pytanie sprowadza się do tego, że zawsze powinieneś przedkładać kompozycję nad dziedziczenie.
Gdyby
Thread
klasa została zadeklarowana jakoabstract
, język musiałby zapewnić inną klasę, która jest z niego rozszerzana, której programiści mogliby użyć do utworzeniaThread
. Twoje pytanie brzmiałoby wtedy, dlaczego ta klasa,extends
z którejThread
pochodzi, nie jestabstract
. Gdyby język nie zapewniał innej klasy,extends
z której pochodziThread
, programiści musieliby stworzyć własną klasę, któraextend
pochodzi z,Thread
i przesłonićrun()
metodę.Jedynym możliwym wyjaśnieniem, jakie mogę dać, jest to, że programiści języka widzieli kilka przypadków użycia do przesłonięcia,
start
gdy klasa została wprowadzona do JDK. Pierwsza wersja Javy, której użyłem, to 1.5 i osobiście nie natknąłem się na przypadek użycia, w którym znalazłem potrzebę przesłonięciastart
. Jak stwierdził JB Nizet w swojej odpowiedziźródło
Możesz oczywiście strzelić sobie w stopę, ale to nie znaczy, że musisz.
Ponieważ zalecanym sposobem tworzenia początku wątku nie jest podklasa Thread. Zalecanym sposobem jest zdefiniowanie a
Runnable
i przekazanie go jako argumentu do konstruktora Thread:Runnable r = new Runnable() { @Override public void run() { ... } }; Thread t = new Thread(r); t.start();
Tak i nie. Nie możesz zastąpić implementacji start () własną implementacją, ale możesz zrobić dodatkowe rzeczy w start (), jeśli chcesz:
@Override public void start() { System.out.println("Did anyone tell you I will spawn a new thread??"); super.start(); }
To powiedziawszy, gdyby Java została dziś przeprojektowana od zera, istnieje duża szansa, że projekt byłby inny. Pamiętaj, że ta klasa pochodzi z języka Java 1.0 i nadal jest kompatybilna wstecz.
źródło
Czy na pewno nigdy nie chciałbyś go zastąpić?
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(); } }; } }
źródło
Uważam, że w odpowiedziach należy opublikować kilka kalirifkacji:
Nie! Wolałbym nie. To tak, jakby powiedzieć: „Czy na pewno chcesz zadeklarować tę zmienną jako prywatną?” Ponieważ gdybym mógł zadeklarować dowolną zmienną, której używam jako publiczną, bez obawy, że inni programiści mogą zepsuć moją logikę projektowania, kodowanie byłoby proste. Jednym z najważniejszych celów OOPS koncepcji zakresu, abstrakcji, polimorfizmu, obsługi błędów itp. Jest przekazanie innym programistom projektu i intencji kryjących się za Twoim kodem. użyć super.start (). @Codebender napisał metodę startową dla wątku bez użycia super.start (), a kompilator nigdy nie narzekał. Więc może złamać cały mechanizm wątkowości, a kompilator ma po prostu pozwolić mu przejść? Metoda startowa wątku zapewnia, że metoda run jest wywoływana i wykonywana we właściwym czasie! Ma to kluczowe znaczenie dla samej koncepcji Threading. Byłbym bardziej niż szczęśliwy, gdybym został poprawiony, gdybym coś tutaj przeoczył. 2.
OK, jeśli projektant pozwala na podbijanie wątku i zepsucie metody startowej, zgodnie z tą logiką projekt strzela sam sobie w stopę. W innym oświadczeniu (z którym całkowicie się zgadzam) Runnable jest zalecanym sposobem. Dlaczego więc w ogóle pozwalamy klasie Thread na tworzenie wystąpienia wątku w ogóle bez żadnych ograniczeń? Następnie następuje:
To faktycznie potwierdza twierdzenie codebender, że metoda start powinna być ostateczna, kiedy to mówisz .. ^
Jedna kwestia, która jest ważna, została już wspomniana na marginesie, ale jest rzeczywistą odpowiedzią na to pytanie
"Kompatybilność wsteczna".
W rzeczywistości ulepszenia wprowadzano nawet dopiero w JDK 5.0, kiedy obejmowały wiele ważnych dodatków i wyjaśnień do modelu współbieżności języka Java. Chcemy, aby w pełni obsługiwana była kompatybilność wsteczna i dlatego klasa Thread jest nadal dokładnie taka, jak była wcześniej, mimo że interfejs Runnable jest obecnie zalecany.
Znowu byłbym bardziej niż szczęśliwy, gdyby został poprawiony, gdybym coś przeoczył.
źródło