etc./StackOverFlow

Java에서 "Runnable 구현" 대 "스레드 확장"

청렴결백한 만능 재주꾼 2021. 11. 26. 06:54
반응형

질문자 :user65374


Java 에서 스레드와 함께 보낸 시간부터 스레드를 작성하는 다음 두 가지 방법을 찾았습니다.

Runnable 구현으로 :

 public class MyRunnable implements Runnable { public void run() { //Code } } //Started with a "new Thread(new MyRunnable()).start()" call

또는 extends Thread :

 public class MyThread extends Thread { public MyThread() { super("MyThread"); } public void run() { //Code } } //Started with a "new MyThread().start()" call

이 두 코드 블록에 큰 차이가 있습니까?



예: Runnable 구현하는 것이 IMO에서 선호하는 방법입니다. 당신은 실제로 스레드의 동작을 전문화하지 않습니다. 당신은 단지 그것을 실행할 무언가를 제공하고 있습니다. 이는 구성철학적으로 "더 순수한" 방법임을 의미합니다.

실용적인 Runnable 을 구현하고 다른 클래스에서도 확장할 수 있다는 것을 의미합니다. Java 8부터 람다 표현식을 통해 Runnable


Jon Skeet

tl;dr: Runnable을 구현하는 것이 더 좋습니다. 단, 주의사항이 중요합니다

Thread 보다 Runnable 과 같은 것을 사용하는 것이 좋습니다. 선택한 동시성과 느슨하게 결합된 작업만 유지할 수 있기 때문입니다. 예를 들어, Runnable 을 사용하고 나중에 이것이 실제로 자체 Thread 필요하지 않다고 결정하면 threadA.run()을 호출하면 됩니다.

주의 사항: 여기에서는 원시 스레드를 사용하지 않는 것이 좋습니다. 나는 CallablesFutureTasks를 사용하는 것을 훨씬 선호합니다(javadoc에서: "취소 가능한 비동기 계산"). 타임아웃의 통합, 적절한 취소 및 최신 동시성 지원의 스레드 풀링은 모두 원시 스레드 더미보다 훨씬 더 유용합니다.

후속 조치: Runnables를 사용할 수 있도록 하는 FutureTask 생성자 가 있습니다(가장 편안한 경우). 여전히 최신 동시성 도구의 이점을 얻을 수 있습니다. javadoc을 인용하려면 :

특정 결과가 필요하지 않은 경우 다음 형식의 구성을 사용하는 것이 좋습니다.

 Future<?> f = new FutureTask<Object>(runnable, null)

따라서 runnablethreadA 다음을 얻습니다.

 new FutureTask<Object>(threadA, null)

Runnables에 더 가까이 머물 수 있는 또 다른 옵션은 ThreadPoolExecutor 입니다. 실행 메소드를 사용하여 "미래의 언젠가 주어진 작업"을 실행하기 위해 Runnable을 전달할 수 있습니다.

스레드 풀을 사용하려는 경우 위의 코드 조각은 다음과 같을 것입니다( Executors.newCachedThreadPool() 팩토리 메서드 사용).

 ExecutorService es = Executors.newCachedThreadPool(); es.execute(new ThreadA());

Bob Cross

이야기의 교훈:

일부 동작을 재정의하려는 경우에만 상속합니다.

또는 다음과 같이 읽어야 합니다.

적게 상속하고 더 많이 인터페이스하십시오.


panzerschreck

글쎄요, 좋은 답변이 너무 많아서 여기에 더 추가하고 싶습니다. Extending v/s Implementing Thread 를 이해하는 데 도움이 될 것입니다.
Extends는 두 개의 클래스 파일을 매우 밀접하게 바인딩하고 일부는 코드를 처리하기 어렵게 만들 수 있습니다.

두 접근 방식 모두 동일한 작업을 수행하지만 몇 가지 차이점이 있습니다.
가장 일반적인 차이점은

  1. Thread 클래스를 확장하면 필요한 다른 클래스를 확장할 수 없습니다. (아시다시피 Java는 둘 이상의 클래스 상속을 허용하지 않습니다.)
  2. Runnable을 구현하면 클래스 공간을 절약하여 미래 또는 현재의 다른 클래스를 확장할 수 있습니다.

그러나 Runnable을 구현하는 것과 Thread를 확장하는 것의 한 가지 중요한 차이점은
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

다음 예는 더 명확하게 이해하는 데 도움이 될 것입니다.

 //Implement Runnable Interface... class ImplementsRunnable implements Runnable { private int counter = 0; public void run() { counter++; System.out.println("ImplementsRunnable : Counter : " + counter); } } //Extend Thread class... class ExtendsThread extends Thread { private int counter = 0; public void run() { counter++; System.out.println("ExtendsThread : Counter : " + counter); } } //Use the above classes here in main to understand the differences more clearly... public class ThreadVsRunnable { public static void main(String args[]) throws Exception { // Multiple threads share the same object. ImplementsRunnable rc = new ImplementsRunnable(); Thread t1 = new Thread(rc); t1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t2 = new Thread(rc); t2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread Thread t3 = new Thread(rc); t3.start(); // Creating new instance for every thread access. ExtendsThread tc1 = new ExtendsThread(); tc1.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc2 = new ExtendsThread(); tc2.start(); Thread.sleep(1000); // Waiting for 1 second before starting next thread ExtendsThread tc3 = new ExtendsThread(); tc3.start(); } }

위 프로그램의 출력.

 ImplementsRunnable : Counter : 1 ImplementsRunnable : Counter : 2 ImplementsRunnable : Counter : 3 ExtendsThread : Counter : 1 ExtendsThread : Counter : 1 ExtendsThread : Counter : 1

Runnable 인터페이스 접근 방식에서는 클래스의 하나의 인스턴스만 생성되고 다른 스레드에서 공유되었습니다. 따라서 카운터 값은 모든 스레드 액세스에 대해 증가합니다.

반면 Thread 클래스 접근 방식에서는 모든 스레드 액세스에 대해 별도의 인스턴스를 만들어야 합니다. 따라서 모든 클래스 인스턴스에 대해 다른 메모리가 할당되고 각각 별도의 카운터가 있으며 값은 동일하게 유지됩니다. 즉, 개체 참조가 동일하지 않기 때문에 증가가 발생하지 않습니다.

언제 Runnable을 사용합니까?
스레드 그룹에서 동일한 리소스에 액세스하려는 경우 Runnable 인터페이스를 사용합니다. 다중 객체 생성은 더 많은 메모리를 소비하고 큰 성능 오버헤드가 되기 때문에 여기에서 Thread 클래스를 사용하지 마십시오.

Runnable을 구현하는 클래스는 스레드가 아니라 클래스일 뿐입니다. Runnable이 Thread가 되려면 Thread의 인스턴스를 만들고 자신을 대상으로 전달해야 합니다.

run() 메서드만 재정의하고 다른 Thread 메서드는 재정의하지 않으려는 경우 사용해야 합니다. 프로그래머가 클래스의 기본 동작을 수정하거나 향상하려는 경우가 아니면 클래스를 하위 클래스로 분류해서는 안 되므로 이는 중요합니다.

슈퍼클래스를 확장해야 하는 경우에는 Thread 클래스를 사용하는 것보다 Runnable 인터페이스를 구현하는 것이 더 적절하다. 스레드를 만들기 위해 Runnable 인터페이스를 구현하는 동안 다른 클래스를 확장할 수 있기 때문입니다.

이것이 도움이 되기를 바랍니다!


Rupesh Yadav

아직 언급되지 않은 한 가지 놀란 점은 Runnable 을 구현하면 클래스가 더 유연해집니다.

스레드를 확장하면 수행 중인 작업은 항상 스레드에 있게 됩니다. Runnable 을 구현하는 경우에는 그럴 필요가 없습니다. 스레드에서 실행하거나 일종의 실행기 서비스에 전달하거나 단일 스레드 응용 프로그램 내에서 작업으로 전달할 수 있습니다(나중에 실행되지만 동일한 스레드 내에서). Thread 바인딩하는 것보다 Runnable 사용하는 경우 옵션이 훨씬 더 많이 열려 있습니다.


Herms

다른 클래스를 구현하거나 확장하려면 Runnable 인터페이스가 가장 바람직하고, 다른 클래스가 확장하거나 구현하지 않으려면 Thread 클래스가 선호됩니다.

가장 일반적인 차이점은

여기에 이미지 설명 입력

extends Thread 클래스를 확장하면 필요한 다른 클래스를 확장할 수 없습니다. (아시다시피 Java는 둘 이상의 클래스 상속을 허용하지 않습니다.)

implements Runnable 을 구현하면 미래 또는 현재 다른 클래스를 확장하기 위해 클래스를 위한 공간을 절약할 수 있습니다.

  • Java는 다중 상속을 지원하지 않습니다. 즉, Java에서 하나의 클래스만 확장할 수 있으므로 Thread 클래스를 확장하면 기회를 놓치고 Java에서 다른 클래스를 확장하거나 상속할 수 없습니다.

  • 객체 지향 프로그래밍에서 클래스 확장은 일반적으로 새로운 기능을 추가하고 동작을 수정하거나 개선하는 것을 의미합니다. Thread를 수정하지 않는다면 Runnable 인터페이스를 대신 사용하십시오.

  • Runnable 인터페이스는 일반 스레드나 실행자 또는 다른 수단으로 실행할 수 있는 작업을 나타냅니다. 따라서 Task를 Thread보다 Runnable로 논리적으로 분리하는 것은 좋은 디자인 결정입니다.

  • 태스크를 Runnable로 분리한다는 것은 태스크를 재사용할 수 있고 다른 수단에서 실행할 수 있다는 것을 의미합니다. 스레드가 완료되면 다시 시작할 수 없기 때문입니다. 다시 Runnable 대 작업에 대한 Thread, Runnable이 승자입니다.

  • Java 디자이너는 이것을 인식하고 이것이 Executors가 Runnable을 Task로 받아들이고 해당 작업을 실행하는 작업자 스레드가 있는 이유입니다.

  • 모든 Thread 메서드를 상속하는 것은 Runnable로 쉽게 수행할 수 있는 Task를 나타내기 위한 추가 오버헤드입니다.

javarevisited.blogspot.com 에서 제공

이것들은 Java에서 Thread와 Runnable 사이의 주목할만한 차이점 중 일부입니다. Thread 대 Runnable에 대한 다른 차이점을 알고 있다면 의견을 통해 공유하십시오. 저는 개인적으로 이 시나리오에서 Runnable over Thread를 사용하며 요구 사항에 따라 Runnable 또는 Callable 인터페이스를 사용할 것을 권장합니다.

그러나 중요한 차이점은 다음과 같습니다.

extends Thread 클래스를 확장하면 각 스레드가 고유한 개체를 만들고 연결합니다. implements Runnable 을 구현하면 동일한 객체를 여러 스레드와 공유합니다.


Nidhish Krishnan

RunnableThread 를 비교하는 것은 현명하지 않습니다.

이 둘은 마치 자동차의 Wheel and Engine 관계처럼 멀티스레딩에서 의존성과 관계를 가지고 있습니다.

두 단계로 멀티스레딩을 수행하는 방법은 단 한 가지뿐입니다. 내 요점을 말하겠습니다.

실행 가능:
interface Runnable 구현할 때 다른 스레드에서 run able 있는 것을 생성한다는 의미입니다. 이제 스레드 내에서 실행할 수 있는 것(스레드 내에서 실행 가능)을 생성한다는 것은 스레드를 생성한다는 의미가 아닙니다.
MyRunnable 클래스는 void run 메서드가 있는 일반 클래스일 뿐입니다. 그리고 그 객체는 호출될 때 정상적으로 run 되는 메소드 실행만 있는 일부 일반 객체가 될 것입니다. (우리가 스레드에서 객체를 전달하지 않는 한).

실:
class Thread start() 메소드를 통해 멀티 스레딩을 가능하게 하는 새로운 Thread를 시작할 수 있는 매우 특별한 클래스라고 말하고 싶습니다.

비교하는 것이 현명하지 않은 이유는 무엇입니까?
멀티 스레딩을 위해서는 둘 다 필요하기 때문입니다.

멀티 스레딩의 경우 두 가지가 필요합니다.

  • 스레드(Runnable) 내에서 실행할 수 있는 것.
  • 새로운 스레드(Thread)를 시작할 수 있는 것.

따라서 기술적으로나 이론적으로 둘 다 스레드를 시작하는 데 필요합니다. 하나는 실행 되고 다른 하나는 실행됩니다 ( Wheel and Engine 처럼).

MyRunnable 로 스레드를 시작할 수 없는 이유 Thread 인스턴스에 전달해야 합니다.

그러나 ThreadRunnable ThreadRunnable 임을 모두 알고 있기 때문에 class Thread 만 사용하여 스레드를 만들고 실행할 수 있습니다.

마지막으로 ThreadRunnable 은 경쟁자나 대체가 아닌 멀티스레딩을 위해 서로 보완적입니다.


Saif

Runnable을 구현해야 하지만 Java 5 이상에서 실행 중인 경우 new Thread 시작하지 말고 대신 ExecutorService 를 사용해야 합니다. 자세한 내용은 Java에서 간단한 스레딩을 구현하는 방법을 참조하세요.


Fabian Steeg

저는 전문가는 아니지만 Thread를 확장하는 대신 Runnable을 구현해야 하는 한 가지 이유를 생각할 수 있습니다. Java는 단일 상속만 지원하므로 하나의 클래스만 확장할 수 있습니다.

편집: 이것은 원래 "인터페이스를 구현하는 데 더 적은 리소스가 필요합니다."라고 말했습니다. 하지만 어느 쪽이든 새로운 Thread 인스턴스를 생성해야 하므로 이것은 잘못된 것이었습니다.


Powerlord

나는 세 번째 방법이 있다고 말하고 싶습니다.

 public class Something { public void justAnotherMethod() { ... } } new Thread(new Runnable() { public void run() { instanceOfSomething.justAnotherMethod(); } }).start();

아마도 이것은 내가 최근에 많이 사용하는 Javascript 및 Actionscript 3에 의해 약간 영향을 받을 수 있지만 이렇게 하면 클래스에서 Runnable 과 같은 꽤 모호한 인터페이스를 구현할 필요가 없습니다.


Bart van Heukelom

Java 8이 출시되면서 이제 세 번째 옵션이 제공됩니다.

Runnable기능적 인터페이스 이므로 람다 식 또는 메서드 참조를 사용하여 인스턴스를 만들 수 있습니다.

귀하의 예는 다음으로 대체될 수 있습니다.

 new Thread(() -> { /* Code here */ }).start()

ExecutorService 및 메서드 참조를 사용하려는 경우:

 executor.execute(runner::run)

이것들은 귀하의 예보다 훨씬 짧을뿐만 아니라 단일 책임 및 스레드 동작을 전문화하지 않기 때문에 구성 사용과 같이 Runnable over Thread 이 방법은 또한 예제에서와 같이 Runnable 필요한 경우 추가 클래스를 만드는 것을 방지합니다.


Alex - GlassEditor.com

인터페이스를 인스턴스화하면 코드와 스레드 구현이 더 명확하게 구분되므로 이 경우 Runnable을 구현하는 것이 좋습니다.


starblue

스레드 확장과 Runnable 구현의 차이점은 다음과 같습니다.

여기에 이미지 설명 입력


Raman Gupta

여기 있는 모든 사람들은 Runnable을 구현하는 것이 가야 할 길이라고 생각하는 것 같습니다. 저는 그들에 동의하지 않지만 제 생각에는 Thread를 확장하는 경우도 있습니다. 실제로 코드에서 일종의 시연을 했습니다.

Runnable을 구현하면 Runnable을 구현하는 클래스는 스레드 이름을 제어할 수 없으며 다음과 같이 스레드 이름을 설정할 수 있는 호출 코드입니다.

 new Thread(myRunnable,"WhateverNameiFeelLike");

그러나 Thread를 확장하면 클래스 자체 내에서 이를 관리할 수 있습니다(예에서 스레드의 이름을 'ThreadB'로 지정하는 것처럼). 이 경우 당신은:

A) 디버깅 목적으로 더 유용한 이름을 지정할 수 있습니다.

B) 그 이름이 해당 클래스의 모든 인스턴스에 사용되도록 강제하고 있습니다(스레드라는 사실을 무시하고 마치 Runnable인 것처럼 위의 작업을 수행하지만 우리는 여기에서 어떤 경우에도 규칙에 대해 이야기하고 있으므로 그렇게 할 수 있습니다. 내가 느끼는 그 가능성을 무시하십시오).

예를 들어 생성의 스택 추적을 가져와 이를 스레드 이름으로 사용할 수도 있습니다. 이상하게 보일 수 있지만 코드가 어떻게 구성되어 있는지에 따라 디버깅 목적으로 매우 유용할 수 있습니다.

이것은 작은 일처럼 보일 수 있지만 많은 스레드가 있는 매우 복잡한 응용 프로그램이 있고 갑자기 모든 것이 '중지'된 경우(교착 상태의 이유로 또는 가능성이 적은 네트워크 프로토콜의 결함으로 인해) 명백한 - 또는 다른 끝없는 이유) 모든 스레드가 'Thread-1','Thread-2','Thread-3'이라고 불리는 Java에서 스택 덤프를 얻는 것이 항상 매우 유용한 것은 아닙니다(스레드가 어떻게 구조화되고 스택 추적만으로 어느 것이 유용하게 말할 수 있는지 여부 - 모두 동일한 코드를 실행하는 여러 스레드 그룹을 사용하는 경우 항상 가능한 것은 아닙니다.

물론 생성 호출의 스택 추적으로 이름을 설정하는 스레드 클래스의 확장을 생성하고 표준 자바 스레드 클래스 대신 Runnable 구현과 함께 이를 사용하여 일반적인 방식으로 위의 작업을 수행할 수도 있습니다. (아래 참조) 그러나 스택 추적 외에도 디버깅을 위해 스레드 이름에 유용한 컨텍스트 특정 정보가 더 있을 수 있습니다(예를 들어 처리할 수 있는 많은 대기열 또는 소켓 중 하나에 대한 참조). 컴파일러가 당신(또는 당신의 라이브러리를 사용하는 다른 사람들)이 이름에 사용하기 위해 특정 정보(예: 문제의 큐/소켓)를 전달하도록 강제할 수 있도록 이 경우에 특별히 스레드를 확장하십시오.

다음은 호출 스택 추적을 이름으로 사용하는 일반 스레드의 예입니다.

 public class DebuggableThread extends Thread { private static String getStackTrace(String name) { Throwable t= new Throwable("DebuggableThread-"+name); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(os); t.printStackTrace(ps); return os.toString(); } public DebuggableThread(String name) { super(getStackTrace(name)); } public static void main(String[] args) throws Exception { System.out.println(new Thread()); System.out.println(new DebuggableThread("MainTest")); } }

다음은 두 이름을 비교하는 출력 샘플입니다.

 Thread[Thread-1,5,main] Thread[java.lang.Throwable: DebuggableThread-MainTest at DebuggableThread.getStackTrace(DebuggableThread.java:6) at DebuggableThread.<init>(DebuggableThread.java:14) at DebuggableThread.main(DebuggableThread.java:19) ,5,main]

AntonyM

다음과 같은 이유로 실행 가능:

  • Runnable 구현이 다른 클래스를 확장할 수 있는 더 많은 유연성을 제공합니다.
  • 코드를 실행과 분리
  • 스레드 풀, 이벤트 스레드 또는 향후 다른 방식으로 실행 파일을 실행할 수 있습니다.

지금은 필요하지 않더라도 나중에 필요할 수도 있습니다. Thread 재정의에 대한 이점이 없으므로 Runnable이 더 나은 솔루션입니다.


n13

이것은 매우 인기있는 주제이고 좋은 답변이 도처에 퍼져 있고 깊이있게 다루어지기 때문에 다른 사람들의 좋은 답변을보다 간결한 형식으로 컴파일하는 것이 정당하다고 생각하여 초보자가 쉽게 개요를 미리 볼 수 있습니다.

  1. 일반적으로 기능을 추가하거나 수정하기 위해 클래스를 확장합니다. 따라서 Thread 동작덮어쓰지 않으려면 Runnable을 사용하십시오.

  2. 같은 맥락에서 스레드 메서드를 상속 할 필요가 없는 경우 Runnable을 사용하여 오버헤드 없이 수행할 수 있습니다.

  3. 단일 상속 : Thread를 확장하면 다른 클래스에서 확장할 수 없으므로 그렇게 해야 하는 경우 Runnable을 사용해야 합니다.

  4. 기술적 수단에서 도메인 논리를 분리하는 것은 좋은 디자인입니다. 그런 의미에서 Runnable 작업이 러너 에서 작업을 분리 하는 것이 더 좋습니다.

  5. 동일한 Runnable 개체를 여러 번 실행할 수 있지만 Thread 개체는 한 번만 시작할 수 있습니다. (아마도 Executors는 Runnable을 허용하지만 Thread는 허용하지 않는 이유일 수 있습니다.)

  6. 작업을 Runnable로 개발 하면 현재와 미래에 사용할 수 있는 모든 유연성이 있습니다. Executors를 통해 동시에 실행되지만 Thread를 통해서도 실행할 수 있습니다. 그리고 다른 일반 유형/객체와 마찬가지로 동일한 스레드 내에서 동시에 사용/호출할 수도 있습니다.

  7. 이렇게 하면 단위 테스트 에서 작업 논리와 동시성 측면을 더 쉽게 분리 할 수 있습니다.

  8. 이 질문에 관심이 있다면 Callable과 Runnable 의 차이점에도 관심이 있을 수 있습니다.


Jörg

이것은 Oracle의 스레드 정의 및 시작 자습서에서 설명합니다.

다음 중 어떤 관용구를 사용해야 합니까? Runnable 객체를 사용하는 첫 번째 관용구는 Runnable 객체가 Thread 이외의 클래스를 하위 클래스로 분류할 수 있기 때문에 더 일반적입니다. 두 번째 관용구는 간단한 응용 프로그램에서 사용하기 더 쉽지만 작업 클래스가 Thread의 자손이어야 한다는 사실에 의해 제한됩니다. 이 단원에서는 Runnable 작업을 작업을 실행하는 Thread 개체와 분리하는 첫 번째 접근 방식에 중점을 둡니다. 이 접근 방식은 더 유연할 뿐만 아니라 나중에 다룰 고급 스레드 관리 API에도 적용할 수 있습니다.

즉, Runnable Thread 이외의 클래스를 확장하는 시나리오에서 작동합니다. Java는 다중 상속을 지원하지 않습니다. 또한 일부 고급 스레드 관리 API를 사용하는 경우 Thread Thread 확장이 선호되는 유일한 시나리오는 향후 업데이트가 적용되지 않는 소규모 응용 프로그램입니다. 프로젝트가 성장함에 따라 더 유연하기 때문에 Runnable 을 구현하는 것이 거의 항상 더 좋습니다. Java에서 많은 인터페이스를 구현할 수 있지만 하나의 클래스만 확장할 수 있으므로 디자인 변경은 큰 영향을 미치지 않습니다.


Sionnach733

가장 간단한 설명은 Runnable 을 구현하여 동일한 객체를 여러 스레드에 할당할 수 있고 각 Thread 는 동일한 객체 상태와 동작을 공유한다는 것입니다.

예를 들어, 두 개의 스레드, thread1 배열 박았 정수와 배열이 가득 할 때 배열에서 정수를 취 thread2가 가정합니다. thread2 가 작동하려면 thread1 이 배열을 채웠는지 여부에 관계없이 배열의 상태를 알아야 합니다.

Runnable 구현하면 객체를 공유할 수 있는 유연성이 있는 반면 extends Thread 는 각 스레드에 대해 새 객체를 생성하므로 thread1에서 수행한 모든 업데이트는 thread2로 손실됩니다.


Shababb Karim

내가 틀리지 않았다면, 그것은 다소 비슷합니다.

인터페이스와 추상 클래스의 차이점은 무엇입니까?

확장은 " Is A " 관계를 설정하고 인터페이스는 " Has " 기능을 제공합니다.

Runnable 구현 선호:

  1. Thread 클래스를 확장하고 Thread API 기본 구현을 수정할 필요가 없는 경우
  2. Fire and Forget 명령을 실행하는 경우
  3. 이미 다른 클래스를 확장하고 있는 경우

" 확장 스레드 " 선호:

  1. Oracle 문서 페이지에 나열된 대로이러한 스레드 메서드를 재정의해야 하는 경우

일반적으로 스레드 동작을 재정의할 필요가 없습니다. 따라서 Runnable을 구현 하는 것이 대부분의 경우 선호됩니다.

다른 참고로, 고급 ExecutorService 또는 ThreadPoolExecutorService API를 사용하면 더 많은 유연성과 제어가 제공됩니다.

이 SE 질문을 살펴보십시오.

ExecutorService 대 캐주얼 스레드 생성기


Ravindra babu

Runnable 구현에서 Thread 클래스를 분리하면 스레드와 run() 메서드 간의 잠재적인 동기화 문제도 피할 수 있습니다. 별도의 Runnable은 일반적으로 실행 가능한 코드가 참조되고 실행되는 방식에 더 큰 유연성을 제공합니다.


Govula Srinivas

Runnable 은 인터페이스이고 Thread 는 이 인터페이스를 구현하는 클래스입니다. 디자인 관점에서 작업이 정의되는 방식과 실행되는 방식 사이에는 명확한 구분이 있어야 합니다. Runnalbe 구현의 책임이고 후자는 Thread 클래스의 작업입니다. 대부분의 경우 Runnable 구현하는 것이 올바른 방법입니다.


developer110

즉,의 SSOLID 싱글 책임 :.

스레드 는 코드 조각의 비동기 실행 의 실행 컨텍스트 (실행 컨텍스트: 스택 프레임, 스레드 ID 등)를 구현합니다. 해당 코드 조각은 동기 또는 비동기 여부에 관계없이 이상적으로 동일한 구현이어야 합니다.

하나의 구현으로 함께 묶으면 결과 객체에 관련 없는 두 가지 변경 원인이 제공됩니다.

  1. 애플리케이션에서 스레드 처리(예: 실행 컨텍스트 쿼리 및 수정)
  2. 코드 조각(실행 가능한 부분)에 의해 구현된 알고리즘

사용하는 언어가 부분 클래스 또는 다중 상속을 지원하는 경우 고유한 수퍼 클래스에서 각 원인을 분리할 수 있지만 기능 세트가 겹치지 않기 때문에 두 객체를 구성하는 것과 동일하게 요약됩니다. 그것은 이론을 위한 것입니다.

실제로, 일반적으로 말해서 프로그램은 필요 이상으로 복잡할 필요가 없습니다. 특정 작업에 대해 작업하는 스레드가 하나 있다면 해당 작업을 변경하지 않고 작업을 별도의 클래스로 만드는 것은 의미가 없으며 코드는 더 간단합니다.

Java 컨텍스트에서 기능이 이미 있으므로 독립 실행형 Runnable 클래스로 직접 시작하고 해당 인스턴스를 Thread (또는 Executor ) 인스턴스에 전달하는 것이 더 쉽습니다. 해당 패턴에 익숙해 지면 실행 가능한 간단한 스레드 케이스보다 사용(또는 읽기)이 더 어렵지 않습니다.


didierc

기본 클래스를 확장하는 대신 인터페이스를 구현하려는 한 가지 이유는 이미 다른 클래스를 확장하고 있기 때문입니다. 하나의 클래스만 확장할 수 있지만 인터페이스는 원하는 수만큼 구현할 수 있습니다.

Thread를 확장하면 기본적으로 'this' 이외의 다른 스레드에서 논리가 실행되는 것을 방지할 수 있습니다. 일부 스레드만 논리를 실행하도록 하려면 Runnable을 구현하는 것이 좋습니다.


Nikhil A A

runnable을 사용하면 공간을 절약하여 다른 클래스로 확장할 수 있습니다.


user2771655

Thread 로 동작하기를 원했던 기본적인 이유를 다시 살펴볼 수 있습니까? 전혀 이유가 없습니다. 우리는 작업을 실행하기를 원했습니다. 가장 가능성이 높은 비동기식 모드입니다. 정확히 말하면 작업 실행이 메인 스레드에서 분기되어야 하고 일찍 완료되면 메인 스레드에서 분기해야 하고 기다리거나 기다리지 않을 수 있습니다. 분기 경로(작업).

이것이 전체 목적이라면 전문 스레드의 필요성을 어디에서 볼 수 있습니까? 이것은 시스템의 스레드 풀에서 RAW 스레드를 선택하고 우리의 작업(클래스의 인스턴스일 수 있음)을 할당하여 수행할 수 있습니다.

따라서 OOP 개념을 따르고 필요한 유형의 클래스를 작성해 보겠습니다. 일을 하는 방법에는 여러 가지가 있으며 올바른 방법으로 하는 것이 중요합니다.

작업이 필요하므로 스레드에서 실행할 수 있는 작업 정의를 작성하십시오. 따라서 Runnable을 사용하십시오.

항상 기억하십시오. implements 는 동작을 전달하는 데 특별히 사용되며 extends 은 기능/속성을 전달하는 데 사용됩니다.

우리는 스레드의 속성을 원하지 않고 대신 우리 클래스가 실행할 수 있는 작업으로 작동하기를 원합니다.


dharam

예, ThreadA call을 호출하면 start 메소드를 호출할 필요가 없고 run 메소드는 ThreadA 클래스를 호출한 후 호출됩니다. 그러나 ThreadB 호출을 사용하는 경우 호출 실행 메서드에 대한 시작 스레드가 필요합니다. 더 도움이 필요하시면 답장을 보내주세요.


Manoj Kumar

언급된 모든 이유로 Runnable을 사용하는 것이 가장 유용하지만 때로는 Thread를 확장하여 나만의 스레드 중지 메서드를 만들고 내가 만든 스레드에서 직접 호출할 수 있습니다.


Tarvaris Jackson

Java는 다중 상속을 지원하지 않으므로 Thread 클래스를 확장하면 다른 클래스가 확장되지 않습니다.

예: 애플릿을 생성하면 애플릿 클래스를 확장해야 하므로 여기서 스레드를 생성하는 유일한 방법은 Runnable 인터페이스를 구현하는 것입니다.


Himanshu Mohta

Thread와 runnable의 차이점 실행 가능한 인터페이스를 구현하여 스레드를 생성하는 경우 여러 스레드를 생성하기 위해 단일 객체를 사용할 수 있습니다. 따라서 단일 객체는 여러 스레드에서 공유됩니다. 따라서 메모리를 덜 차지합니다.

따라서 데이터가 민감하지 않은 경우 요구 사항에 따라 다릅니다. 따라서 여러 Thread 간에 공유할 수 있으므로 Runnable 인터페이스를 사용할 수 있습니다.


Rohit Chugh

여기에 내 두 센트를 추가하십시오 . 가능한 한 항상 implements Runnable 합니다. extends Thread 사용하지 말아야 하는 이유에 대한 두 가지 주의 사항입니다.

  1. 이상적으로는 Thread 클래스를 확장해서는 안 됩니다. Thread 클래스는 final 이어야 합니다. thread.getId() 와 같은 메소드. Thread 확장과 관련된 버그에 대해서는 이 토론을 참조하세요.

  2. 퍼즐을 푸는 것을 좋아하는 사람들은 Thread를 확장하는 또 다른 부작용을 볼 수 있습니다. 아래 코드는 아무도 알리지 않을 때 연결할 수 없는 코드를 인쇄합니다.

http://pastebin.com/BjKNNs2G 를 참조하십시오.

 public class WaitPuzzle { public static void main(String[] args) throws InterruptedException { DoNothing doNothing = new DoNothing(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); new WaitForever(doNothing).start(); Thread.sleep(100); doNothing.start(); while(true) { Thread.sleep(10); } } static class WaitForever extends Thread { private DoNothing doNothing; public WaitForever(DoNothing doNothing) { this.doNothing = doNothing; } @Override public void run() { synchronized (doNothing) { try { doNothing.wait(); // will wait forever here as nobody notifies here } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Unreachable Code"); } } } static class DoNothing extends Thread { @Override public void run() { System.out.println("Do Nothing "); } } }

veritas

출처 : http:www.stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread-in-java

반응형