14_멀티스레드
14_멀티스레드
Java 멀티 스레드
14.1 멀티 스레드 개념
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 멀티 스레드 개념 예시
public class MultiThreadExample {
public static void main(String[] args) {
// 두 개의 작업을 동시에 실행
Thread task1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("작업 1 실행 중...");
try { Thread.sleep(500); } catch (Exception e) {}
}
});
task1.start(); // 새로운 스레드에서 실행
// 메인 스레드는 별도로 계속 실행
for (int i = 0; i < 5; i++) {
System.out.println("메인 작업 실행 중...");
try { Thread.sleep(500); } catch (Exception e) {}
}
}
}
- 멀티 스레드는 하나의 프로그램에서 여러 작업을 동시에 실행할 수 있게 해주는 기술입니다.
14.2 메인 스레드
1
2
3
4
5
6
7
8
public class MainThreadExample {
public static void main(String[] args) {
// 현재 실행 중인 메인 스레드 정보 출력
Thread mainThread = Thread.currentThread();
System.out.println("프로그램 시작 스레드 이름: " + mainThread.getName());
System.out.println("우선순위: " + mainThread.getPriority());
}
}
- 메인 스레드는
main()메소드를 실행하는 스레드로, JVM이 시작할 때 자동으로 생성됩니다.
14.3 작업 스레드 생성과 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 방법 1: Thread 클래스 상속
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread 상속받은 작업 스레드 실행");
}
}
// 방법 2: Runnable 인터페이스 구현
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable 구현한 작업 스레드 실행");
}
}
// 사용 예시
public class ThreadExample {
public static void main(String[] args) {
// Thread 상속 방식
MyThread thread1 = new MyThread();
thread1.start();
// Runnable 구현 방식
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
// 람다식 사용
Thread thread3 = new Thread(() -> {
System.out.println("람다식으로 구현한 작업 스레드 실행");
});
thread3.start();
}
}
- 작업 스레드는 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하여 생성하고,
start()메소드로 실행합니다.
14.4 스레드 이름
1
2
3
4
5
6
7
8
9
10
11
12
public class ThreadNameExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("현재 스레드 이름: " + Thread.currentThread().getName());
});
thread.setName("작업스레드1"); // 스레드 이름 설정
thread.start();
System.out.println("메인 스레드 이름: " + Thread.currentThread().getName());
}
}
- 스레드 이름은
setName()메소드로 설정하고getName()메소드로 조회할 수 있으며, 디버깅 시 유용합니다.
14.5 스레드 상태
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ThreadStateExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(3000); // 3초간 일시 정지
} catch (InterruptedException e) {}
});
System.out.println("스레드 시작 전 상태: " + thread.getState()); // NEW
thread.start();
System.out.println("스레드 시작 후 상태: " + thread.getState()); // RUNNABLE
try { Thread.sleep(500); } catch (Exception e) {}
System.out.println("스레드 일시 정지 상태: " + thread.getState()); // TIMED_WAITING
try { thread.join(); } catch (Exception e) {}
System.out.println("스레드 종료 후 상태: " + thread.getState()); // TERMINATED
}
}
- 스레드 상태는 NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED 등으로 분류되며
getState()메소드로 확인할 수 있습니다.
14.6 스레드 동기화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class SynchronizedExample {
private static int counter = 0;
// 동기화 메소드
public synchronized static void increment() {
counter++;
}
// 동기화 블록
public static void incrementBlock() {
synchronized(SynchronizedExample.class) {
counter++;
}
}
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("최종 카운터 값: " + counter); // 20000이 나와야 함
}
}
- 스레드 동기화는
synchronized키워드를 사용하여 여러 스레드가 공유 자원에 동시에 접근하는 문제를 해결합니다.
14.7 스레드 안전 종료
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SafeStopExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (!Thread.interrupted()) { // 인터럽트 확인
System.out.println("작업 실행 중...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// InterruptedException 발생 시 스레드 종료
System.out.println("인터럽트 발생, 스레드 종료");
break;
}
}
System.out.println("작업 종료");
});
thread.start();
try { Thread.sleep(3000); } catch (Exception e) {} // 3초 동안 실행
thread.interrupt(); // 스레드 안전하게 종료 요청
}
}
- 스레드 안전 종료는
interrupt()메소드와interrupted()확인을 통해 스레드를 안전하게 종료할 수 있게 합니다.
14.8 데몬 스레드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DaemonThreadExample {
public static void main(String[] args) {
Thread daemon = new Thread(() -> {
while (true) {
System.out.println("데몬 스레드 실행 중...");
try { Thread.sleep(1000); } catch (Exception e) {}
}
});
daemon.setDaemon(true); // 데몬 스레드로 설정
daemon.start();
try { Thread.sleep(3000); } catch (Exception e) {}
System.out.println("메인 스레드 종료");
// 메인 스레드 종료 시 데몬 스레드도 자동 종료
}
}
- 데몬 스레드는
setDaemon(true)로 설정하며, 주 스레드가 종료되면 함께 종료되는 백그라ун드 작업용 스레드입니다.
14.9 스레드풀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 고정 크기 스레드풀 생성 (최대 2개 스레드)
ExecutorService executor = Executors.newFixedThreadPool(2);
// 작업 제출
for (int i = 0; i < 5; i++) {
final int taskNum = i;
executor.execute(() -> {
System.out.println("작업 " + taskNum + " 실행 중, 스레드: " +
Thread.currentThread().getName());
try { Thread.sleep(1000); } catch (Exception e) {}
});
}
// 스레드풀 종료
executor.shutdown();
}
}
- 스레드풀은
ExecutorService를 통해 생성하며, 작업량이 많을 때 스레드 생성 비용을 줄이고 자원을 효율적으로 관리합니다.
This post is licensed under CC BY 4.0 by the author.