스레드 생성과 실행
1. 스레드 생성
스레드 생성 - Thread 상속
public class HelloThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " : run()");
}
}
// ...
public class HelloThreadMain {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + ": main() start");
HelloThread helloThread = new HelloThread();
System.out.println(Thread.currentThread().getName() + ": start() 호출 전");
helloThread.start();
System.out.println(Thread.currentThread().getName() + ": start() 호출 후");
System.out.println(Thread.currentThread().getName() + ": main() end");
}
}
// 실행 결과
main: main() start
main: start() 호출 전
main: start() 호출 후
Thread-0: run()
main: main() end위 코드의 실행 결과를 보게 되면 스레드 생성 전후 메모리 변화가 아래와 같이 일어나는 것을 확인할 수 있다.
메서드를 실행하면 스택프레임을 스택에 올리면서 시작한다.
스레드 간의 실행 순서는 얼마든지 달라질 수 있다.
CPU 코어가 2개여서 물리적으로 정말 동시에 실행될 수 있고, 하나의 CPU 코어에서 시간을 나누어 실행될 수도 있다.
그리고 한 스레드가 얼마나 오랜기간 실행되는지도 보장하지 않는다. 한 스레드가 먼저 다 수행한 후 다른 스레드가 수행될 수도 있고, 둘이 번갈아 가면서 수행할 수도 있다.
스레드는 순서와 실행 기간을 모두 보장하지 않는다.
스레드 순서와 실행 기간은 운영체제가 결정하는 것이지, 애플리케이션 코드에서 결정하는 것이 아니다.
이것이 멀티 스레드!


데몬 스레드
스레드는 사용자 스레드와 데몬 스레드 2 종류로 구분할 수 있다.
사용자 스레드
프로그램의 주요 작업을 수행한다.
작업이 완료될 때가지 실행된다.
모든 사용자 스레드가 종료되면 JVM 도 종료된다.
데몬 스레드
백그라운드에서 보조적인 작업을 수행한다.
모든 사용자 스레드가 종료 되면 데몬 스레드는 자동으로 종료된다.
스레드 생성 - Runnable 상속
스레드를 만들 때는
Thread클래스를 상속 받는 방법과Runnable인터페이스를 구현하는 방법이 있다.
Thread 상속 vs Runnable 구현
결론 : 쓰레드를 사용할 때는 Runnable 인터페이스를 구현하는 방법을 사용하자.
Thread 상속
장점
간단한 구현
단점
상속의 제한 : 자바는 클래스는 단일 상속이다. (
extends)하지만 현실에서는 다른 클래스들을 상속하면서 동시에 쓰레드를 사용할 경우가 많다.
이런 경우
Runnable인터페이스 상속을 통해서 개선할 수 있다.
유연성 부족 : 인터페이스를 사용하는 방법에 비해서 유연성이 떨어진다.
비지니스 로직, 쓰레드 상태(
started,interrupted등), 실행 메커니즘이 하나의 쓰레드 객체에 섞인다.Runnable인터페이스 사용을 통해 다음과 같이 작업을 분리해야 유연성이 높아진다.Runnable: 실행 로직Thread: 쓰레드 제어
Runnable 구현
장점
상속의 자유로움 : 인터페이스는 다중 상속이 가능하다. (
implements)코드의 분리 : 스레드 실행 로직과 스레드 제어 작업을 분리해 가독성(유지보수)을 향상시킬 수 있다.
자원의 공유 : 여러 스레드가 동일한
Runnable객체를 공유할 수 있다.
단점
코드가 약간 복잡해 질 수 있다.
2. Runnable 을 만드는 다양한 방법
정적 중첩 클래스 사용
익명 클래스 사용
익명 클래스 변수 없이 직접 전달
람다
Last updated