|
112 | 112 | - 상수로 리턴됨. 위의 웨이팅, 타임웨이팅 .. 외에도 뉴,러너블 등이 있다.
|
113 | 113 |
|
114 | 114 |
|
115 |
| -
|
116 | 115 | ## 6.스레드 싱태 제어
|
| 116 | +- 실행중인 스레드의 형태를 변경하는 것을 스레드 상태 제어라고 한다. |
| 117 | +- 잘 사용하면 약이 되지만, 잘못 사용하면 치명적 버그가 되므로 사용하는 법을 잘 숙지해야한다. |
| 118 | +- 제어를 제대로 하기 위해서, 상태 변화를 가져오는 메소드들을 알아야한다. |
| 119 | +
|
| 120 | +1. 주어진 시간동안 일시 정지 sleep() |
| 121 | + - 실행 중인 스레드를 일정 시간 멈추게 하고 싶다면 Thread 클래스의 정적 메소드인 sleep() 사용 |
| 122 | + - 메소드를 호출한 스레드는 주어진 시간 동안 일시 정지 상태 -> 이후 다시 실행 대기 상태로 돌아감 |
| 123 | +2. 다른 스레드에게 실행 양보 yield() |
| 124 | + - 스레드가 처리하는 작업은 반복적인 실행을 위해 for/while을 포함하는 경우가 있는데, 이런 반복문이 무의미한 반복을 하는 경우가 있다. 계속 도는거지 |
| 125 | + - yield() 메소드를 호출한 스레드는 실행 대기 상태로 돌아가고 동일한 우선순위 or 높은 우선순위를 갖는 스레드가 실행 기회를 가질 수 있도록 한다. |
| 126 | +3. 다른 스레드의 종료를 기다림 join() |
| 127 | + - 다른 스레드가 종료될 때까지 기다렸다가 실행해야하는 경우가 발생한다면? |
| 128 | + - 예를 들어 계산작업을 하는 스레드가 있으면, 계산결과를 받아 실행해야하는 스레드가 있을 것이다. |
| 129 | + - 이 경우 ThreadA가 ThreadB 의 join() 메소드를 호출하면 A는 B가 종료할 때까지 일시 정지 상태가 된다. 계산하는 애가 작업을 마칠 때까지 일시 정지 상태에 있다가 최종 계산된 결과값을 산출, 종료하면 값을 받아 출력한다. |
| 130 | + - Thread.join(); |
| 131 | +4. 스레드의 안전한 종료 - stop플래그 / interrupt() |
| 132 | + - 스레드는 자신의 run() 메소드가 모두 실행되면 자동으로 종료되지만, 실행중인 스레드를 바로 종료시켜야할 때가 있다. |
| 133 | + - 예를들어 비디오 일시정지 |
| 134 | + - Thread는 stop()을 통해 스레드를 즉시 종료시켰지만 비정상적인 종료로 스레드 자원이 불안정하게 남겨지면 deprecated 되었고, stop 플래그 or interrupt() 메소드를 권장한다. |
| 135 | + - 1. stop 플래그 - while(!stop) |
| 136 | + - 2. interrupt() - 예외를 발생시킨다. 이를 통해 run() 메소드를 정상적으로 종료시킨다. (InterruptedException) |
| 137 | + - 인터럽트 메소드가 실행되면 인터럽티드익셉션이 바로 발생하는 것이 아니라 스레드가 미래에 **일시정지 상태가 되어야 예외가 발생**한다. |
| 138 | + - 일시정지 여부를 확인하려면 : isInterrupted() |
| 139 | +
|
117 | 140 |
|
118 | 141 | ## 7.데몬 스레드
|
| 142 | +- 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드 |
| 143 | +- 주 스레드가 종료되면 데몬 스레드는 강제로 종료 |
| 144 | +- 데몬스레드와 주스레드 큰 차이 없음 |
| 145 | +- 주 스레드가 종료되면 같이 종료된다. |
| 146 | +- 스레드를 데몬으로 만들고 싶다면 : setDemon(true) 호출 |
| 147 | +- 실행중인 스레드가 데몬스레드인지 확인 : isDaemon() 리턴값 확인 |
119 | 148 |
|
120 | 149 | ## 8.스레드 그룹
|
| 150 | +- 스레드 그룹은 관련된 스레드를 묶어서 관리할 목적으로 이용됨. |
| 151 | +- 스레드는 반드시 하나의 스레드 그룹에 포함되는데, 명시적으로 스레드 그룹에 안넣으면 기본적으로 자기를 만든 스레드와 같은 스레드에 속한다. |
| 152 | +- 보통 main 스레드가 다른 스레드 생성하므로 여기에 많이 속함 |
121 | 153 |
|
122 |
| -## 9.스레드풀 |
| 154 | +1. 스레드 그룹 이름 얻기 |
| 155 | + - getThreadGroup(); |
| 156 | + - getAllStackTraces(); : map 타입의 객체 리턴 |
| 157 | +
|
| 158 | +2. 스레드 그룹 생성 |
| 159 | + - 부모 스레드 안정하면 현재 스레드는 부모 스레드 하위로 들어감 |
| 160 | + - ThreadGroup tg = new ThreadGroup(String name); |
| 161 | +
|
| 162 | +3. 스레드 그룹의 일괄 interrupt() |
| 163 | + - 스레드 그룹에 들어가면 뭐가 좋나요 -> 일괄 interrupt rksmdgka. |
| 164 | + - 10개 스레드를 종료시키기 위해 하나씩 인터럽트 거는 것보다 10개 한번에 거는 것이 편함 |
123 | 165 |
|
124 | 166 |
|
| 167 | +## 9.스레드풀 |
| 168 | +- 병렬 작업 처리가 많아지면 스레드 개수 증가 -> CPU : 스레드도 만들고 스케쥴링도 해야하고 메모리 사용도 많아짐 |
| 169 | +- 작업의 폭증으로 인한 스레드 폭증을 막으려면 스레드 풀을 사용해야 한다. |
| 170 | +- 사용되는 **스레드를 제한된 개수만큼 정해놓고 작업큐에 들어오는 작업을 하나씩 맡아 처리한다.** |
| 171 | +- 자바에서 스레드풀 사용을 위해 제공하는 것 |
| 172 | + - 1. Executors 클래스 |
| 173 | + - 2. ExecutorService 인터페이스 |
| 174 | +
|
| 175 | +[동작과정] |
| 176 | + 1. 어플이 스레드풀에 작업처리 요청 |
| 177 | + 2. 스레드풀: 작업큐에 업무들 말아넣고 각 스레드는 큐에서 하나씩 가져와서 열심히 일함 |
| 178 | + - 스레드1: 일할게 |
| 179 | + - 스레드2: 일할게 |
| 180 | + - 스레드3: 일할게.. |
| 181 | + 3. 작업 결과를 전달함 |
| 182 | +
|
| 183 | +1. 스레드풀 생성 및 종료 |
| 184 | + 1. 생성 : newCachedThreadPool(), newFixedThreadPool() |
| 185 | + 2. 종료 : shutdowu(), shutdownNow() |
| 186 | +
|
| 187 | +
|
| 188 | +2. 작업 생성과 처리 요청 |
| 189 | + 1. 생성 : Runnable(리턴값 X), Callable(리턴값 O) |
| 190 | + 2. 처리 요청 : execute(), submit() |
| 191 | +
|
| 192 | +
|
| 193 | +3. 블로킹 방식의 작업 완료 통보 |
| 194 | + - submit() 메소드는 매개값으로 준 러너블, 콜러블 작업을 스레드풀의 작업 큐에 저장하고 즉시 **Future 객체를 리턴**한다. |
| 195 | + - 퓨처 객체: 작업이 완료될 때까지 기다렸다가 (지연 == 블로킹 되었다가) 최종 결과를 얻는데 사용된다. |
| 196 | + - 그래서 퓨쳐 객체를 pending completion (지연 완료) 객체라고도 한다. |
| 197 | + - Future.get() 메소드를 호출하면 스레드가 작업을 완료할때까지 블로킹되었다가 작업이 완료되면 처리 결과를 리턴한다. |
| 198 | + - 작업을 처리하는 스레드가 작업 완료하기 전까지 get() 메소드가 블로킹되므로 다른 코드를 실행할 수 없다. |
| 199 | +
|
| 200 | + - (3-1) 리턴값이 없는 작업 완료 통보 |
| 201 | + - 리턴값이 없는 작업일 경우, Runnable 객체로 생성하면 된다. |
| 202 | + |
| 203 | + - (3-2) 리턴값이 있는 작업 완료 통보 |
| 204 | + - 이 경우는 Callable 객체로 생성하기. 이 때 제네릭 타입 T는 call() 메소드가 리턴하는 타입이 되도록 하기 |
| 205 | + |
| 206 | + - (3-3) 작업 처리 결과를 외부 객체에 저장 |
| 207 | + - 스레드가 작업한 결과를 외부 객체에 저장해야할 경우. |
| 208 | + - 스레드 1의 결과 + 스레드 2의 결과 -> result 결과 취합 -> 결과 사용 |
| 209 | + - 이런 작업을 위해서 ExecutorService의 submit(Runnable tast, V result) 메소드를 사용할 수 있다. (여기서 V가 result 타입) |
| 210 | + |
| 211 | + - (3-4) 작업 완료 순으로 통보 |
| 212 | + - 작업 요청 순서대로 처리가 완료되는 것은 아니다. 양도 다르고, 스케쥴링에 따라서도 처리 순서는 달라진다. |
| 213 | + - 스레드 풀에서 작업 처리가 완료된 것만 통보받으려면? **CompletionService** 사용하기 |
| 214 | + - poll(), take(), submit() |
| 215 | +
|
125 | 216 |
|
| 217 | +4. 콜백 방식의 작업 완료 통보 |
| 218 | + - 어플리케이션이 스레드에게 작업 처리를 요청한 후, 스레드가 작업을 요청하면 **특정 메소드를 자동 실행**하는 방법. |
| 219 | + - **자동 실행되는 메소드를 콜백 메소드라 한다.** |
| 220 | + - 작업 처리를 요청한 후 결과를 기다릴 필요 없이 다른 기능을 수행할 수 있다. (블로킹 방식은 작업 처리를 요청하고 작업이 완료될 때까지 블로킹되는 것과 비교됨) |
0 commit comments