스레드 (Thread)
스레드는 프로그램의 실행 흐름으로 프로세스의 내부에 존재한다.
프로세스에 비해 필요 자원이 적으며 같은 프로세스 내의 스레드 간 자원을 공유한다,
Java는 멀티태스킹을 위해 멀티스레딩 방식을 사용한다.
이를 통해 유휴시간을 최소화하여 CPU의 사용률을 높일 수 있게 한다.
모니터 (Monitor)
Java는 Monitor mechanism을 이용한다.
Monitor란 스레드 간 상호배제(mutual exclusion)를 구현하는 동기화 구조이다.
스레드가 오브젝트 조작 시 모니터 확보를 필요로 한다.
이를 통해 특정 스레드가 모니터를 가지면 오브젝트에 락을 설정하여 다른 스레드가 해당 오브젝트에 접근할 수 없게 한다.
Main thread
Main thread는 Java 프로그램 시작 시 실행되는 기본 스레드로 프로그램 종료 직전까지 실행되는 마지막 스레드이다,
자식 스레드를 생성하면 Main thread를 기점으로 생성된다.
스레드 제어
모든 스레드는 Thread 오브젝트로 제어할 수 있다.
currentThread()는 현재 스레드에 접근할 수 있는 메서드로 시그니처는 아래 코드와 같다.
public static Thread currentThread()
currentThread()는 현재 실행 스레드의 오브젝트 참조를 반환한다.
따라서 아래 코드를 통해 현재 스레드를 확인하는 것이 가능하다.
class Example {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println("Current thread : " + t);
}
}
자식 스레드 생성
자식 스레드를 생성하는 방법으로 Runnable 인터페이스 구현하는 방법과 Thread 자식 클래스를 정의하는 방법이 있다.
1. Runnable 인터페이스 구현 클래스 정의
Runnable 인터페이스 구현 클래스는 public void run()을 멤버 메서드로 갖는다.
run() 내부에 스레드가 실행할 코드를 작성하여 구현한다.
따라서 아래코드처럼 작성하여 자식 스레드를 생성하는 것이 가능하다.
class MyRunnable implements Runnable {
public void run() {
// 스레드 안에서 실행할 코드
}
}
class Example {
public static void main(String[] args) {
Thread nowThread = Thread.currentThread();
System.out.println("현재 스레드 : " + nowThread);
Thread t = new Thread(new MyRunnable());
t.start();
System.out.println("자식 스레드 : " + t);
}
}
2. Thread 상속 클래스 정의
Thread 클래스를 상속받는 클래스를 사용할 때에도 run() 내부에 스레드가 실행할 코드를 작성하여 구현한다.
class MyThread extends Thread {
public void run() {
// 스레드 안에서 실행할 코드
}
}
class Example {
public static void main(String[] args) {
Thread nowThread = Thread.currentThread();
System.out.println("현재 스레드 : " + nowThread);
MyThread t = new MyThread();
t.start();
System.out.println("자식 스레드 : " + t);
}
}
Thread 클래스의 유용한 멤버 메서드는 아래와 같다.
static Thread currentThread() | 현재 실행 중인 스레드 객체의 참조 값 반환 |
String getName() | 스레드의 이름을 반환 |
int getPriority() | 스레드의 우선순위 값을 반환 |
boolean isInterrupted() | 스레드가 인터럽트를 당했는지 여부를 반환 |
void setName() | 스레드의 이름을 설정 |
void setPriority() | 스레드의 우선순위를 설정 |
final boolean isAlive() | 스레드가 실행 중인지 여부를 반환 |
final void join() throws InterruptedException | 메인 스레드가 특정 스레드의 종료를 기다림 |
Thread 클래스의 오버로딩된 생성자는 다음과 같다.
Thread() | 스레드 객체를 생성 |
Thread(Runnable target) | Runnable 구현 객체를 사용해 스레드 객체를 생성 |
Thread(Runnable target, String name) | Runnable 구현 객체를 사용해 스레드 이름이 name인 스레드 객체를 생성 |
아래 코드를 통해서 두 스레드가 동시에 실행되는 것을 확인할 수 있다.
class MyThread extends Thread {
MyThread() {
super();
System.out.println("child thread : " + this);
}
public void run() {
try {
for (int i = 5; i > 0;i--) {
System.out.println("Child thread : " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Child thread exiting.");
}
}
class Example {
public static void main(String[] args) {
Thread nowThread = Thread.currentThread();
System.out.println("현재 스레드 : " + nowThread);
MyThread t = new MyThread();
t.start();
System.out.println("자식 스레드 : " + t);
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread : "+i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
두 방식에는 각각 장단점이 있다.
run() 외 메서드를 오버라이딩 할 필요가 있을 때에는 Thread 클래스를 사용하는 것이 편리하고
run() 메서드만 구현하면 되거나 다른 클래스를 상속해야할 때에는 Runnable 구현 클래스를 사용하는 것이 편리하다.
'Java > Java 문법' 카테고리의 다른 글
[Java] 열거형 (enum) (0) | 2024.12.01 |
---|---|
[Java] 레이스 컨디션 (Race Condition), 스레드 동기화 (synchronized) (0) | 2024.12.01 |
[Java] 예외 처리 (검사형 예외, 비검사형 예외) (0) | 2024.10.27 |
[Java] Iterator 인터페이스 (0) | 2024.10.14 |
[Java] 컬렉션 프레임워크 (Collection Framework), List 인터페이스 (List interface) (0) | 2024.10.14 |