Thread가 추상 클래스가 아니고 start ()가 final이 아닌 이유는 무엇입니까?


79

Thread클래스가 추상 클래스가 아닌 일반 클래스로 구현 된 이유는run() 메서드가 추상 인

문제가 생길 수 있습니까? 아니면 이런 식으로 사용합니까?

또한이 Thread.start()메서드는 다른 클래스에서 기능을 구현할 수없는 매우 구체적인 메서드 여야합니다 (내가 틀리지 않은 경우). 따라서 final키워드가 다른 방법보다 더 적합 할 것이라고 생각합니다 .

하지만이 방법을 재정의하고 원하는대로 사용할 수 있습니다.

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??");
    }
}

분명히 인쇄 만했는데

누군가 내가 새 스레드를 생성 할 것이라고 말했습니까 ??

엔지니어가 당신을 대체하는 것을 혼란스럽게하는 것 외에 재정의에 어떤 용도가 있습니까?

그렇지 않다면 왜 메소드가 Thread 클래스에서 final로 선언되지 않았습니까?


다음은 클래스의 구성원으로 방법의 시작을 요구하고있다 ... 그것은 ... 스케줄러에서 호출하지
CoderNeji

2
명확성을 위해-사용자가 재정의해야하므로 Thread.run ()이 추상이 아닌 이유와 Thread.start ()가 최종이 아닌 이유를 묻습니다. 좋은 질문! 누군가가 반대표를 던진 것을 발견했습니다. 이유가 궁금합니다.
NickJ 2015

3
차라리 Thread수업이 마지막 이었으면 좋겠어요 . 생성자는 이미 실행 가능 파일을 사용하므로 스레드를 만드는 데 상속이 필요하지 않습니다.
rightfold

답변:


50

Thread 클래스가 run () 메서드가 추상 인 추상 클래스가 아닌 일반 클래스로 구현 된 이유는 무엇입니까?

이 질문은 실제로 상속보다 구성을 선호해야한다는 사실로 귀결됩니다.

경우 Thread클래스가 선언 된 abstract언어는 프로그래머가를 만드는 데 사용할 수있는 그것에서 확장 된 다른 클래스를 제공 할 것입니다 Thread. 이 클래스의 것을 왜 귀하의 질문은 다음에 대한 것 extends부터가 Thread아니다 abstract. 언어가 extends에서 온 다른 클래스를 제공하지 않으면 Thread프로그래머는 메서드 extend에서 시작 Thread하고 재정의하는 자체 클래스를 만들어야합니다 run().

그렇지 않다면 왜 메소드가 Thread 클래스에서 final로 선언되지 않았습니까 ??

내가 줄 수있는 유일한 설명은 언어 개발자가 start클래스가 JDK에 도입되었을 때 재정의하는 몇 가지 사용 사례를 보았다 는 것입니다. 내가 사용한 Java의 첫 번째 버전은 1.5였으며 개인적으로을 재정의해야하는 사용 사례를 발견하지 못했습니다 start. JB Nizet이 그의 답변에서 말했듯이

Java가 오늘 처음부터 다시 디자인 되었다면 디자인이 다를 가능성이 높습니다.


1
스레드 이름 지정을 위해 Thread 클래스를 확장 할 필요는 없지만 (Thread.setName () 호출 만하면됩니다), 클래스가 추상이 될 수없는 이유를 설명하는 부분은 매우 명확하고 정확합니다 ...
Codebender

@Codebender 동의합니다. 나는 그것이 좋은 예가 아니었고 귀하의 질문이 언제 스레드 를 확장 해야하는지 묻지 않았기 때문에 내 대답에서 제거했습니다 .
CKing 2015

깔끔한 디자인입니다. 오늘은 왜 다를까요?
Warren Dew

76

물론 발로 자신을 쏠 수도 있지만 그렇다고해서 반드시해야하는 것은 아닙니다.

Thread 클래스가 run () 메서드가 추상 인 추상 클래스가 아닌 일반 클래스로 구현 된 이유는 무엇입니까?

시작 스레드를 만드는 데 권장되는 방법은 Thread를 하위 클래스로 만드는 것이 아니기 때문입니다. 권장되는 방법은를 정의 Runnable하고 Thread 생성자에 인수로 전달하는 것입니다.

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

따라서 최종 키워드가 다른 방법보다 더 적합 할 것이라고 생각합니다.

예, 아니오. start () 구현을 자체 구현으로 대체 할 수는 없지만 원하는 경우 start ()에서 추가 작업을 수행 할 수 있습니다 .

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

즉, Java가 오늘 처음부터 다시 디자인 되었다면 디자인이 다를 가능성이 높습니다. 이 클래스는 Java 1.0에서 시작되었으며 여전히 이전 버전과 호환됩니다.


나는 내 대답에서 당신을 인용했습니다. :) 당신과 함께 괜찮 희망
요리하는

11
문제 없어요. 오픈 소스입니다.
JB Nizet

2
@NayukiMinase 아니. 인터페이스는 항상 언어로되어 있습니다. Runnable은 JDK 1.0부터 존재합니다.
JB Nizet

죄송합니다. 인터페이스 콜백을 기반으로하는 새로운 AWT 이벤트 처리 시스템 (메서드 재정의가 아닌)이 1.1에서 도입 된 방법과 혼동되었습니다.
Nayuki

1
실은 깔끔한 디자인입니다. 오늘은 왜 다를까요?
Warren Dew

40

Thread.start()그렇지 final않습니까?

당신이 있습니까 장해야 당신이 그것을 무시하고 싶지는 않을 것이다?

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();
            }
        };
    }
}

0

답변에 대한 몇 가지 calirifcations가 게시되어야한다고 생각합니다.

"당신은 그것을 무시하고 싶지 않을 것이 확실합니까?"

아니 ! 내가 않을 것. "정말로이 변수를 private으로 선언 하시겠습니까?"라고 말하는 것과 같습니다. 다른 개발자가 내 디자인 로직을 엉망으로 만들지 않을까 걱정하지 않고 내가 사용하는 변수를 공개로 선언 할 수 있다면 코딩이 수월 할 것입니다. 범위, 추상화, 다형성, 오류 처리 등의 OOPS 개념의 가장 중요한 목적 중 하나는 다른 개발자에게 코드이면의 디자인과 의도를 전달하는 것입니다. 질문에서 지적했듯이 시작 메서드를 재정의 할 때 아무도 강제하지 않습니다. super.start ()를 사용합니다. @Codebender는 super.start ()를 사용하지 않고 스레드에 대한 시작 메서드를 작성했으며 컴파일러는 불평하지 않았습니다. 그래서 그는 스레딩의 전체 메커니즘을 자유롭게 깰 수 있으며 컴파일러는 그냥 통과시키는 것으로 가정합니까? 스레드의 시작 메서드는 run 메서드가 적절한 시간에 호출되고 실행되도록합니다! 스레딩이라는 개념에 매우 중요합니다. 여기에서 뭔가를 놓친 경우 수정되어 기쁠 것입니다. 2.

스레드를 시작하는 데 권장되는 방법은 Thread를 하위 클래스로 만드는 것이 아니기 때문입니다.

좋아, 만약 codebender가 디자인에 의해 허용된다면, Thread를 sublass하고 시작 방법을 엉망으로 만들 수 있습니다. 그 논리에 의해, 그것은 디자인 자체가 발을 쏘는 것입니다. (내가 완전히 동의하는) 다른 진술에 따르면 Runnable이 권장되는 방법입니다. 그렇다면 왜 Thread 클래스가 제한없이 스레드를 인스턴스화하도록 허용합니까? 다음은 다음과 같습니다.

start () 구현을 자신의 구현으로 바꿀 수는 없습니다.

그것은 실제로 시작 방법이 최종적이어야한다는 코드 벤더의 주장을 뒷받침합니다 .. ^

유효한 한 가지 요점은 이미 부수적으로 언급되었지만 이 질문에 대한 실제 답변입니다.

"하위 호환성".

사실 Java 동시성 모델에 대한 많은 주요 추가 및 설명을 통합 한 JDK 5.0까지 개선이 진행되었습니다. 우리는 이전 버전과의 호환성이 항상 지원되기를 원하며, 이것이 오늘날 Runnable 인터페이스가 권장되는 방법 임에도 불구하고 Thread 클래스가 이전과 똑같은 이유입니다.

다시 말하지만, 내가 뭔가를 놓친 경우 수정되는 것보다 기쁠 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.