사전적 의미로 한 가닥의 실이라는 뜻으로 한가지 작업을 실행하기 위해 순차적으로 실행할 코드를 실처럼 이어놓았다고 해서 유래된 이름이다. 하나의 스레드는 하나의 코드 실행 흐름이므로 한 프로세스 내 스레드가 2개라면 2개의 실행 흐름이 생긴다.
프로세스가 할당받은 자원을 이용하는 실행의 단위이며
- 프로세스 내의 명령어 블록으로 시작점과 종료점을 가진다.
- 실행중에 멈출 수 있으며 동시에 수행 가능하다.
- 어떠한 프로그램 내에서 특히 프로세스 내에서 실행되는 흐름의 단위이다.
자바에서는 멀티 스레딩을 통해 하나의 프로세스 내에서 여러 스레드가 병렬로 실행될 수 있다.
스레드의 특징
- 공유 주소 공간 : 같은 프로세스 내의 스레드들은 동일한 메모리 공간을 공유한다. 이를 통해 스레드 간 데이터 공유와 통신이 매우 효율적이다.
- 독립적인 실행 흐름 : 각 스레드는 자신만의 실행 흐름을 가지며, 독립적으로 스케줄링되어 실행할 수 있다.
- 스레드 동기화 : 스레드들이 같은 자원을 동시에 접근할 때 발생할 수 있는 문제를 방지하기 위해 동기화 메커니즘이 필요하다 자바에서는 'synchronized' 키워드와 'java.util.concurrent' 패키지의 여러 클래스를 통해 동기화를 지원한다.
- 생성 및 관리 : 자바에서 스레드는 두 가지 방법으로 실행할 수 있다.
- 'Tread' 클래스를 상속받아 새로운 클래스를 만들고 'run()' 메서드를 오버라이딩
- 'Runnable' 인터페이스를 구현하여 스레드 객체에 전달
// Thread 클래스를 상속받아 스레드 생성
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running.");
}
}
MyThread t1 = new MyThread();
t1.start();
// Runnable 인터페이스를 구현하여 스레드 생성
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running.");
}
}
Thread t2 = new Thread(new MyRunnable());
t2.start();
스레드의 동작을 확인할 수 있는 예제
public class Sample extends Thread {
int seq;
public Sample(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq + " thread start."); // 쓰레드 시작
try {
Thread.sleep(1000); // 1초 대기한다.
} catch (Exception e) {
}
System.out.println(this.seq + " thread end."); // 쓰레드 종료
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) { // 총 10개의 쓰레드를 생성하여 실행한다.
Thread t = new Sample(i);
t.start();
}
System.out.println("main end."); // main 메서드 종료
}
}
위의 예제는 총 10개의 스레드를 실행시키는 예제이다. 어떤 스레드인지 확인하기 위해 스레드마다 생성자에 순서를 부여한다. 그리고 시작과 종료를 출력하게 했고 시작과 종료 사이에 1초의 간격이 생기도록 Tread.slepp(1000) 을 작성하였다. 그리고 main 메서드 종료 시 'main.end'를 출력하도록 했다. 결과를 보자
0 thread start.
4 thread start.
6 thread start.
2 thread start.
main end.
3 thread start.
7 thread start.
8 thread start.
1 thread start.
9 thread start.
5 thread start.
0 thread end.
4 thread end.
2 thread end.
6 thread end.
7 thread end.
3 thread end.
8 thread end.
9 thread end.
1 thread end.
5 thread end.
결과는 출력 때마다 다르다. 0번 스레드부터 9번 스레드까지 순서대로 실행되지 않고, 그 순서가 일정하지 않은 것을 보면 스레드는 순서에 상관없이 동시에 실행된다는 사실을 알 수 있다. 더욱 놀라운 사실은 스레드가 종료되기 전 main 메서드가 종료되었다는 사실이다.
그렇다면 모든 스레드가 종료된 후에 main 메서드를 종료하고 싶은 경우에는 어떻게 해야 할까?
import java.util.ArrayList;
public class Sample extends Thread {
int seq;
public Sample(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq+" thread start.");
try {
Thread.sleep(1000);
}catch(Exception e) {
}
System.out.println(this.seq+" thread end.");
}
public static void main(String[] args) {
ArrayList<Thread> threads = new ArrayList<>();
for(int i=0; i<10; i++) {
Thread t = new Sample(i);
t.start();
threads.add(t);
}
for(int i=0; i<threads.size(); i++) {
Thread t = threads.get(i);
try {
t.join(); // t 쓰레드가 종료할 때까지 기다린다.
}catch(Exception e) {
}
}
System.out.println("main end.");
}
}
생성된 스레드를 ArrayList 객체인 threads 에 담은 후 main 메서드가 종료되기 전에 threads 객체에 담긴 각각의 스레드에 join 메서드를 호출하여 스레드가 종료될때까지 대기하도록 했다. join 메서드는 스레드가 종료될 때까지 기다리게 하는 메서드이다.
0 thread start.
5 thread start.
2 thread start.
6 thread start.
9 thread start.
1 thread start.
7 thread start.
3 thread start.
8 thread start.
4 thread start.
0 thread end.
5 thread end.
2 thread end.
9 thread end.
6 thread end.
1 thread end.
7 thread end.
4 thread end.
8 thread end.
3 thread end.
main end.
이렇게 하면 'main end.' 문자열이 가장 마지막에 출력되는 것을 확인할 수 있다.
'Back-End > Java' 카테고리의 다른 글
할머니도 이해할 수 있는 자바 Thread (0) | 2025.05.01 |
---|---|
try-catch (0) | 2024.07.06 |
프로세스 (0) | 2024.07.04 |
Java HTTP 통신 (1) | 2024.06.12 |
Exception과 Transaction (0) | 2024.02.05 |