이것도 모르고 자바를 했다니..
자바 IO/NIO 프로그래밍 책을 보던중에 아래와 같은 예제를 볼 수 있었다.
public class ExtendThread extends Thread {
@Override
public void run() {
System.out.println("Thread 클래스 상속");
}
}
class ExtendThreadTest {
public static void main(String[] args) {
Thread thread = new ExtendThread();
thread.start();
}
}
상속을 통해 Thread를 생성하고 시작하는 방식의 대한 예제이다.
위에 예제는 상속을 통해 Thread를 생성하고 시작하는 방식이다. 근데 여기서 의문이 생겼다 왜 run() 메서드를 재정의 했는데 사용할 때는 start() 메서드를 사용하는 것이지..?
차이를 알고 이것도 모르고 자바를 했다니 하면서 부끄러웠지만.. 혹시 저 처럼 모르는 사람이 있을 수 있으니 공유해 보려합니다🥲
우선 두 개의 메서드를 확인해 보자
private Runnable target;
/**
* If this thread was constructed using a separate
* {@code Runnable} run object, then that
* {@code Runnable} object's {@code run} method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of {@code Thread} should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the {@code run} method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* {@code start} method) and the other thread (which executes its
* {@code run} method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* @throws IllegalThreadStateException if the thread was already started.
* @see #run()
* @see #stop()
*/
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
위에 코드를 확인 해보면 아래와 같은 내용을 확인할 수 있습니다.
run() 메소드
- Thread 클래스에서 재정의 해 실행할 작업을 정의합니다.
- 이 메소드를 직접 호출하는 것은 단순한 메소드 호출일 뿐 스레드를 추가로 할당하지 않습니다. 즉, 현재 스레드(
run()
을 호출한 스레드)에서 작업을 수행합니다. 그래서 실행 흐름을 차단합니다.
start() 메소드
- start() 메소드는 새로운 스레드를 생성하고 생성한 스레드에서 run() 메소드를 비동기적으로 실행합니다.
- 결과적으로 두 개의 스레드가 동시에 실행됩니다. 긜고 스레드를 두 번 이상 시작하는 것이 허용되지 않습니다.
여기서 start() 메소드의 두 번 이상 시작이 허용되지 않는다는게 궁금했습니다. 아래와 같은 코드는 예외를 발생시키는데 이유는 start() 메소드에 threadStatus 를 확인 하는 부분을 볼 수 있습니다. 현재 스레드 상태가 new 가 아니라면 예외를 발생시킵니다.
public static void main(String[] args) {
Thread thread = new Thread(new RunnableThread());
thread.start();
thread.start();
}
start() 메소드를 실행하게 되면 스레드를 할당한 후 실행 가능 상태가 되면 run() 메소드를 호출하고 작업이 모두 완료되면 스레드를 종료해 예외가 발생하는 것을 확인할 수 있었습니다.
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new RunnableThread());
System.out.println("staus = " + thread.getState()); // staus = NEW
thread.start(); // Runnable 인터페이스를 구현
Thread.sleep(100);
System.out.println("staus = " + thread.getState()); // staus = TERMINATED
}
'BE > Java' 카테고리의 다른 글
[Java] LocalDateTime 정밀도 테스트 실패 (0) | 2023.10.28 |
---|---|
[Java] List를 정렬하는 여러가지 방법 (2) | 2022.11.23 |
String vs StringBuffer vs StringBuilder (0) | 2022.11.07 |
[Java] 자바11의 간단한 설명 (2) | 2022.10.31 |
[Java] 객체 지향 설계 5원칙(SOILD) (0) | 2022.08.31 |