//스레드 상태, 일시정지, 안전한 종료, 데몬스레드//
스레드의 상태를 변경해서 스레드를 제어하는 방법을 공부하는 챕터
cf) start()메소드를 사용했다고 해서 바로 실행되는 건 아니다. 사실은 실행 대기 상태가 된다.
실행 대기 상태에서 run()메소드 내용이 모두 실행되면 스레드의 실행이 멈추고 종료
<<공부할 내용>>
ㅇ스레드 상태
ㅇ스레드 상태 제어
ㄴ주어진 시간 동안 일시정지
ㄴ스레드의 안전한 종료
ㅇ데몬스레드
스레드 상태
ㅇ실행(running)상태 :
ㄴ스레드 객체 생성 -> start() 메소드 호출 => 실행 대기 상태 (실행을 기다리고 있는 상태)
ㄴ운영체제는 실행 대기 상태의 스레드 중 하나의 스레드를 선택하고, CPU(코어)가 run()메소드를 실행하도록 한다. 이 때를 실행상태라고 한다.
ㄴ실행상태의 스레드는 run()메소드를 모두 실행하기 전에 다시 실행대기 상태로 돌아갈 수 있다. 그리고 실행 대기 상태에 있는 다른 스레드가 선택되어 실행 상태가 되고.. 이런식으루 실행상태와 실행대기상태를 번갈아가면서 각 스레드의 run()메소드를 조금씩 실행해나간다.
ㅇ종료(terminated)상태 :
ㄴ실행상태에서 run()메소드가 종료되면 더이상 실행할 코드가 없다. 스레드의 실행이 멈추게 된다.
=>종료 상태
ㅇ일시정지 상태 :
ㄴ경우에 따라서 실행상태에서 일시정지 상태로 가기도 한다. =>스레드가 실행할 수 없는 상태!!
ㄴ바로 실행 상태로 돌아갈 수 없다. 일시정지 상태에서 빠져나와 '실행 대기 상태로 가야 한다'
스레드 상태 제어
ㅇ실행 중인 스레드의 상태를 변경하는 것
ㅇ정교한 스레드 상태 제어가 필요 :
잘못된 상태제어는 먹통을 만든다. 스레드의 상태변화를 만드는 메소드를 잘 파악해야 한다.
1) 주어진 시간 동안 일시정지
2) 스레드의 안전한 종료
1) 주어진 시간 동안 일시정지
★Thread클래스의 정적 메소드 sleep() 사용하기 (1/1000초 단위)
(저번 예제에서 다뤘었다!! try-catch문 속에 넣었었는데!!)
ㄴ일시정지 시간 다 가기 전에 interrupt() 메소드를 호출한다면
InterruptedException이 발생한다. => 그래서 예외 처리가 필요했던 것
ㄴsleep()메소드에서 일시정지 시간이 끝나면 자동적으로 실행 대기 상태가 된다.
★Interrupt() 메소드 : 일시 정지 상태의 스레드에서 InterruptedException을 발생시키기 때문에
예외처리 코드(catch)를 써서 실행대기상태로 가거나 종료상태로 갈 수 있도록 한다.
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
//interrupt() 메소드가 호출되면 실행
}
<<3초 주기로 10번 비프음을 발생하게 하는 예제>>
sleep()메소드 실행으로 메인스레드를 3초동안 일시정지 상태로 보내고,
3초 후 다시 실행준비상태로 돌아온다.
2) 스레드의 안전한 종료
ㅡ해당 스레드의 run() 메소드가 모두 실행되면 자동으로 스레드가 종료된다.
ㅡ하지만 실행중인 스레드를 종료시켜야 한다면?? (예: 동영상을 중간에 끈다)
+불안전한 stop() 메소드는 deprecated다 : 이걸로 갑자기 종료하게 되면 스레드가 사용중이던 자원(파일, 네트워크 연결)들이 불안전한 상태로 남겨지기 때문에, 이제 사용되지 않는다고 한다.
"안전하게"스레드를 종료하려면? ㅡ stop 플래그 이용하기
=>run()메소드의 정상적인 종료를 유도한다.
★stop플래그 필드를 boolean으로 선언해서 while문을 작성하는 방식!
<<예제ㅣ setStop() >>
실행하고 1초 후 setStop(true)
(출력작업스레드 start()로 실행대기상태->실행 1초 할 수 있도록 메인스레드를 setStop(true)코드 실행 전에 1초동안 sleep(1000)로 일시정지키켰다.)
++ interrupt() 메소드를 이용하는 방법
헉 예외 발생하면 안되는게 아니었구나
스레드가 일시정지 상태일 때 interrupt()메소드는 InterruptedException을 발생시키는 역할을 하는데
이걸 이용하면 run()메소드를 정상 종료할 수 있다고 한다!! 아 예외를 이용해서 정상종료를해??
아 이런 방식으로
ㅇThreadA에서 ThreadB의 interrupt()메소드를 실행 -> ThreadB가 sleep()메소드로 '일시정지 상태가 될 때' ThreadB에서 InterruptedException이 발생 -> 예외처리(catch)블록으로 이동 즉 while문을 빠져나올 수 있게 되고, 정리할거 정리한 뒤 run()메소드를 종료할 수 있게 된다.
<<예제 - InterruptedException을 일으켜서 스레드를 종료시키기>>
시작후 일단 메인스레드는 1초동안 일시정지 상태에 들어가고, 1초가 지나면 작업thread에 interrupt()를 작동시킨다.
이렇게 interrupt()메소드가 걸린 상태에서.. 작업thread가 일시정지 상태가 되면 (Thread.sleep(1);) 예외가 발생하여 catch블록으로 가서 while문을 빠져나올 수 있게 된다.
+스레드가 저어어 나중에라도 일시정지 상태가 되지 않으면 interrupt()메소드 호출은 아무의미가 없다.
+interrupt()메소드가 호출된 상태인지 확인하는 방법+
->호출되었다면 다음 두 메소드가 true를 리턴한다.
boolean status = Thread.interrupted();
boolean status = objThread.isInterrupted();
둘 중 아무거나 써도 무방하다 한다.
-interrupted() => 정적 메소드 => 현재 스레드가 interrupted되었는지 확인한다.
-isInterrupted() => 인스턴스 메소드 => 현재 스레드가 interrupted되었는지 확인한다.
<<작업스레드의 interrupt()가 호출되었는지 확인하기>>
이번엔 sleep(1)메소드를 사용하지 않고 interrupted()메소드로 확인해보자.
이렇게 if문을 이용해 interrupted() true가 맞으면 break를 통해서 while문을 빠져나올 수 있다..
데몬스레드
>주 스레드 돕는 "보조적인 스레드" => 주스레드가 종료되면 데몬스레드는 자동 강제종료!!
>이 점 빼면 일반 스레드와 데몬 스레드는 큰 차이 없다.
데몬스레드 적용 예: 워드프로세서의 자동저장, 미디어플레이어의 동영상 및 음악 재생, 쓰레기 수집기
>>주 스레드(워드, 플레이어, JVM)이 종료되면 같이 종료되는 데몬 스레드
★스레드를 데몬으로 만드는 방법
=> 주 스레드가 setDaemon(true)를 호출하면 된다.
Thread1 thread = new Thread1();
thread.setDaemon(true);
thread.start();
.
.
!! thread.start();전에 setDaemon(true) 해야 한다. 안 그러면 IllegalThreadStateException 발생한다.
!! 현재 실행 중인 스레드가 데몬스레드인지 확인하려면 isDaemon() 메소드의 리턴값을 보자.
<<주스레드, 데몬 스레드 예제>>
데몬스레드가 1초간격으로 save()하다가, 메인스레드가 종료되면 데몬스레드도 종료되는 것을 볼 수 있다.
'JAVA' 카테고리의 다른 글
[혼자 공부하는 자바] 7/31 13-1 [List 컬렉션] [ArrayList] [Vector] [LinkedList] (0) | 2020.07.31 |
---|---|
[혼자 공부하는 자바] 7/31 13-1 [컬렉션 프레임워크] (0) | 2020.07.31 |
[혼자 공부하는 자바] 7/29 12-1 [스레드] [멀티 스레드] [프로세스] [작업 스레드] [메인 스레드] [공유객체] [동기화메소드] (0) | 2020.07.29 |
[혼자 공부하는 자바] 7/28 11-2 [java.util 패키지] (0) | 2020.07.29 |
HashMap이 뭘까\('o')/?? (0) | 2020.07.26 |