Thread
Process와 Thread
- Process에서 실제로 작업을 수행하는 것은 Thread이다.
- Process
- Program을 실행하면 Operating System (OS)은 실행에 필요한 자원을 할당받아 Process가 된다.
- Process의 자원을 이용해서 실제로 작업을 수행하는 것은 Thread이다.
- 모든 Process는 최소한 하나 이상의 Thread가 존재한다.
- Process가 가질 수 있는 Thread의 개수는 제한되어 있지 않다.
- Thread가 작업을 수행하는 데 개별적인 Memory 공간인 Call Stack을 필요로 하기 때문에 Memory에 의존적이다.
Thread 구현
- Thread Class를 상속받아 구현하는 방법
- Java는 단일 상속을 지원하기 때문에 Thread Class를 상속받는 경우 다른 Class를 상속받을 수 없다.
- Runnable Interface를 구현하는 방법
- Java의 단일 상속으로 인해 Runnable Interface를 구현하는 방법이 일반적이다.
- 재사용성 (Reusability)이 높고 Code의 일관성 (Consistency)을 유지할 수 있기 때문에 보다 객체지향적인 방법이라 할 수 있다.
- Runnable Interface는 오로지 run()만 정의되어 있는 간단한 Interface이다.
- Thread Class => https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
- Thread Class를 상속받아 run()을 정의하면 된다.
- Runnable Interface => https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html
- Runnable Interface는 오로지 run()만 정의되어 있는 간단한 Interface이다.
- Runnable Interface에 정의되어 있는 abstract method인 run()을 정의하면 된다.
- Runnable Interface를 구현한 Class의 Instance를 생성한 다음 Thread의 생성자의 Parameter로 제공해야 한다.
Thread의 실행
- Thread를 구현한 Class instance에서 start()를 호출하면 Thread가 실행된다.
- start()가 호출되었다고 해서 즉각 실행되는 것은 아니다.
- Thread의 실행 순서는 OS Scheduler에 의해 결정된다.
- 실행 대기 상태 (Runnable)에 있다가 자신의 차례가 되는 경우 실행된다.
- 한 번 실행이 종료된 Thread는 다시 실행할 수 없다.
- 하나의 Thread에 대해 start()가 단 한 번만 호출 가능하며, 두 번 이상 호출하는 경우 IlleagalThreadStateException이 발생한다.
- 하나의 Thread에 대해 start()가 단 한 번만 호출 가능하며, 두 번 이상 호출하는 경우 IlleagalThreadStateException이 발생한다.
- start()가 호출되었다고 해서 즉각 실행되는 것은 아니다.
- run()을 호출하는 경우
- run()을 호출하는 것은 생성된 Thread를 실행시키는 것이 아니라 단순히 Class에 선언된 method를 호출하는 것이다.
- run()을 호출하는 것은 생성된 Thread를 실행시키는 것이 아니라 단순히 Class에 선언된 method를 호출하는 것이다.
- start()를 호출하는 이유
Thread의 우선순위
- Thread는 priority라는 Member Variable을 가지고 있으며, 이 값에 따라 Thread의 실행 시간이 달라진다.
- ☑ 즉, 작업의 중요도에 따라 Thread의 우선순위를 서로 다르게 설정해 특정 Thread가 더 많은 작업시간을 갖도록 설정할 수 있다.
- Thread가 가질 수 있는 우선순위의 범위는 1부터 10까지이며 숫자가 높을수록 우선순위가 높다.
- !주의사항
- Thread를 실행하기 전에만 우선순위를 변경할 수 있다.
- Thread의 우선순위는 Thread를 생성한 Thread로 부터 상속받는다.
Thread Group
- 서로 관련된 Thread를 Group으로 관리하기 위해 Thread Group을 제공한다.
- Thread Group은 Thread의 Set을 나타낸다.
- Thread Group을 생성해서 Thread를 Group으로 묶어서 관리할 수 있다.
- ☑ Thread Group은 다른 Thread Group을 포함할 수 있다.
- Thread Group은 보안상의 이유로 도입되었다.
- 자신이 속한 Thread Group에 대한 정보 Access가 가능하다.
- ☑ Thread Group의 Parent Thread Group이나 다른 Thread Group에 대한 정보에는 액세스할 수 없습니다.
- Initial Thread Group을 제외한 모든 Thread Group은 부모를 갖는 Tree를 형성한다.
- 모든 Thread는 반드시 Thread Group에 포함되어 있어야 한다.
- ☑ Group을 지정하지 않고 Thread를 생성하는 경우, 기본적으로 자신을 생성한 Thread와 같은 Thread Group에 속하게 된다.
- 우리가 생성하는 모든 Thread Group은 main Thread Group의 하위 Thread Group이 된다.
- ☑ Group을 지정하지 않고 Thread를 생성하는 경우, Thread는 자동적으로 main Thread Group에 속하게 된다.
- setMaxPriority()는 Thread가 Thread Group에 추가되기 이전에 호출해야 한다.
Daemon Thread
- daemon Thread는 Thread의 작업을 돕는 역할을 수행한다.
- Thread가 종료되는 경우 daemon Thread는 자동 종료된다.
- daemon Thread가 보조적인 역할을 수행하기 때문에 Thread가 종료되면 daemon Thread가 존재할 이유가 없다.
- Thread를 생성하고 실행하기 전 setDaemon(ture)을 호출해 주면 daemon Thread로 생성된다.
- daemon Thread가 생성한 Thread는 자동적으로 daemon Thread가 된다.
- setDaemon method는 반드시 start()를 호출하기 전에 실행되어야 한다.
- 그렇지 않으면 IllegalThreadStateException이 발생한다.
- 그렇지 않으면 IllegalThreadStateException이 발생한다.
Thread의 실행 제어
- 정교한 Scheduling을 통해 Process에게 주어진 자원을 여러 Thread가 효율적으로 사용해야한다.
- Synchronization과 Scheduling이 Thread Programming을 어렵게 만드는 요소이다.
- 효율적인 Multi-Thread Programming을 개발하기 위해서는 정교한 Scheduling을 통해 Process에게 주어진 자원을 낭비 없이 사용해야 한다.
- ☑ 우선순위를 이용하여 Scheduling이 가능하지만 한계가 존재한다.
- 효율적인 Multi-Thread Programming을 개발을 위해서는 Thread State와 Thread Scheduling에 관련된 Method에 대해서 잘 알고있어야한다.
Thread의 State
[NEW] => Thread가 생성되고 아직 start()가 호출되지 않은 상태
[RUNNABLE] => 실행 가능한 상태
[BLOCKED] => Lock이 풀릴 때까지 기다리는 상태
[WAITING] => Thread의 작업이 종료되지 않았지만, 실행 가능하지 않은 (unrunnable) 일시정지 상태
[TIMED_WAITING] => 일시정지시간이 지정된 상태를 의미
[TERMINATED] => Thread의 작업이 종료된 상태
Thread의 동기화
- Thread Synchronization : 하나의 Thread가 진행 중인 작업을 다른 Thread가 방해하지 못하도록 하는 것
- Multi Thread Process
- 여러 Thread가 같은 Process 내의 자원을 공유해서 작업하기 때문에 서로의 작업에 영향을 미칠 수 있다.
- 문제를 해결하기 위해 Critical Section과 Lock의 개념을 사용한다.
- Shared Data를 사용하는 Code 영역을 Critical Section으로 지정한다.
- Shared Data (Object)가 가지고 있는 Lock을 획득한 단 하나의 Thread만 이 영역의 Code를 수행할 수 있게 한다.
- 해당 Thread가 Critical Section 내의 모든 Code를 수행한 뒤 Lock을 반환해 다른Thread가 수행할 수 있도록 해준다.
- 모든 Object는 Lock을 가지고 있다.
public synchronized void method() {
// 메소드 전체
}
public void method() {
synchronized(공유객체) {
// 단 하나의 스레드만 실행하는 영역
}
}
Thread Pool
ExecutorService threadPool = new ThreadPoolExecutor(
3, // 코어 스레드 개수
100, // 최대 스레드 개수
120L, // 놀고 있는 시간
TimeUnit.SECONDS, // 놀고 있는 시간 단위
new SynchronizedQueue<Runnalbe>() // 작업 큐
);
// 스레드풀 생성
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 작업 생성과 처리 요청
// 스레드풀 종료
executorService.shutdownNow();
'CS > Network' 카테고리의 다른 글
[Network] 이런저런~ (0) | 2024.08.06 |
---|---|
[Network] 구현 코드 깃 링크 (0) | 2024.03.30 |
[Network] Socket (0) | 2024.03.30 |
[Network] Router (0) | 2024.03.30 |
[Network] Network Layer (0) | 2024.03.30 |