1. 프로세스와 쓰레드
- 프로세스는 실행 중인 프로그램을 말한다.
- 프로그램을 실행하면 OS로부터 메모리를 할당받아 프로세스가 된다.
- 프로세스는 데이터, 메모리 등의 자원과 '쓰레드'로 구성되어 있다.
- 자원을 이용하여 실제로 작업을 수행하는 것이 '쓰레드'이다.
- 모든 프로세스에는 최소한 하나 이상의 쓰레드가 존재하며, 두 개 이상일 경우 멀티 쓰레드라고 한다.
멀티태스킹과 멀티쓰레딩
- 멀티태스킹은 다중작업을 말한다. 멀티태스킹이 가능하면 여러 개의 프로세스가 동시에 실행될 수 있다.
- 멀티쓰레딩은 하나의 프로세스 내에서 여러 쓰레드가 동시에 작업을 수행한다.
멀티쓰레딩의 장단점
장점
- CPU의 사용률을 향상시킨다.
- 자원을 효율적으로 사용할 수 있다.
- 사용자에 대한 응답성이 향상된다.
- 작업이 분리되어 코드가 간결해진다.
단점
- 쓰레드 중 한 쓰레드만 문제가 있어도, 전체 프로세스에 영향을 준다.
- 쓰레드를 많이 생성할 경우 성능이 저하된다.(Context Switching)
2. 쓰레드의 구현과 실행
- 쓰레드를 구현하는 방법은 Thread 클래스를 상속받거나 Runnable 인터페이스를 구현하면 된다.
- Thread 클래스를 상속받으면 다른 상속이 불가능하기 때문에 Runnable 인터페이스 구현이 좋다.
class ThreadEx implements Runnable {
public void run() {
// 작업 내용
/.../
}
}
- 예시
class ThreadExample {
public static void main(String args[]) {
Runnable r = new ThreadEx();
Thread t = new Thread(r);
t.start();
}
}
class ThreadEx implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
// currentThread() - 현재 실행중인 thread 리턴
// getName() - thread의 이름을 리턴
// 결과
// Thread-0
// Thread-0
// Thread-0
// Thread-0
// Thread-0
쓰레드의 실행
- 쓰레드 실행은 start()로 한다.
- 쓰레드 실행 시 대기하다가 자신의 차례에서 실행된다.
- 한 번 실행이 종료된 쓰레드는 다시 실행할 수 없다. 다시 하기 위헤서는 새롭게 쓰레드를 생성하고 실행해야한다.
ThreadEx t = new Thread();
t.start();
t = new ThreadEx()l
t.start();
3. start()와 run()
- run()은 클래스에 선언된 메소드를 호출하는 역할
- run()실행 시 호출스택(call stack)에서 main 스택 위에 run 스택이 쌓인다.
- start()는 새로운 쓰레드가 작업을 실행하는데 필요한 호출스택을 생성한 다음에 run()을 호출해서, 생성된 호출 스택에 run()이 처음으로 올라가게 한다.
- 모든 쓰레드는 독립적인 작업을 위해 자신만의 call stack을 필요로 한다.
- 새로운 쓰레드를 생성하고 실행할 때 마다 새로운 call stack이 생성되고 쓰레드가 종료되면 작업에 사용된 call stack은 소멸된다.
- 쓰레드가 여러 개 일 경우 스케줄러가 순서를 정한다.
- 쓰레드는 사용자 쓰레드, 데몬 쓰레드 두 종류가 있다.
- 실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다.
4. 싱글쓰레드와 멀티쓰레드
- 왼쪽은 하나의 쓰레드로 두 작업을 처리함 -> t1이 끝날 때 까지 t2는 대기
- 오른쪽은 두 개의 쓰레드로 두 작업을 처리함 -> t1과 t2가 번갈아 가며 작업
- 두 개의 쓰레드가 번갈아 가며 작업하는 것을 Context Switching이라고 한다.
- 컨텍스트 스위칭 때문에 하나의 쓰레드보다 작업이 오래 걸리는 경우도 있다.
- 여러 쓰레드가 여러 작업을 동시에 진행하는 것을 병행이라고 한다.(concurrent)
- 하나의 작업을 여러 쓰레드가 나눠서 처리하는 것을 병렬이라고 한다.(parallel)
5. 쓰레드의 우선순위
쓰레드의 우선순위 지정하기
- 쓰레드의 우선순위는 setPriority()에 int값으로 정한다.
- 우선순위의 범위는 1~10이다.
- main 쓰레드의 우선순위는 5이다.
6. 데몬 쓰레드(daemom thread)
- 데몬 쓰레드는 일반 쓰레드의 작업을 돕는 쓰레드이다.
- 일반 쓰레드가 모두 종료되면 데몬 쓰레드는 강제적으로 종료된다.
- 예시로 가비지 컬렉터
- 데몬 쓰레드는 무한루프와 조건문을 이용해서 실행 후 대기하고 있다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.
- 데몬 쓰레드가 생성한 쓰레드는 자동으로 데몬 쓰레드가 된다.
- 데몬 쓰레드는 setDaemon(true)를 호출해서 데몬 쓰레드로 변경하여 사용한다.
class ThreadEx implements Runnable {
static boolean authSave = false;
public static void main(String[] args) {
Thread t = new Thread(new ThreadEx());
t.setDaemon(true); // 이 부분이 없으면 종료되지 않음
t.start();
for (int i = 1; i <= 10; i++) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {}
System.out.println(i);
if (i == 5) autoSave = true;
}
System.out.println("프로그램 종료!");
}
public void run() {
while (true) {
try {
Thread.sleep(3*1000); // 3초마다
} catch(InterruptedException e) {}
// autoSave의 값이 true이면 autoSave()를 호출한다.
if (autoSave) autoSave();
}
}
public void autoSave() {
System.out.println("자동저장!");
}
}
// 실행 결과
// 1
// 2
// 3
// 4
// 5
// 6
// 자동저장!
// 7
// 8
// 자동저장!
// 9
// 10
// 프로그램 종료!
- setDaemon()은 반드시 start() 호출 전 실행되어야 한다.
'개발 > Java&Kotlin' 카테고리의 다른 글
[Spring] 동시성 이슈 해결 방법 (1) (0) | 2022.09.20 |
---|---|
[Java] 쓰레드(Thread)의 실행제어 (1) | 2022.09.15 |
[Java] 열거형(enums) (0) | 2022.09.13 |
[Spring] 스프링시큐리티 OAuth2.0 적용해보기(Naver) (0) | 2022.09.02 |
[Spring] 스프링시큐리티 OAuth2.0 적용해보기(Facebook) (0) | 2022.09.01 |