Runnable 인터페이스로 다른 스레드에서 코드를 실행하는 방법과 진해지는 정도의 수준.
그리고 스레드 클래스의 유용한 기능을 알아보고 IDE를 사용해 스레드를 디버그 하는 법도 해볼게요.
1. 스레드 생성하는 방법
Java 에서는 JDK 가 모든 스레드의 관련 속성과 메서드를 스레드 클래스로 압축합니다.
그래서 새 스레드를 만들려면 새 스레드 객체부터 생성해야하죠!! 스레드 객체 자체는 기본적으로 비어있스빈다.
그러니 runnable 인터페이스를 구현하는 클래스의 객체를 해당 생성자에 전달해야합니다.
run 메서드에 어떤 코드를 넣든 운영 체제가 스케줄링하자마자 새 스레드에서 실행될 겁니다.
자바 8부터는 람다로 줄일수 있죠?!?!
스레드 객체에서 start 메서드를 호출해 스레드를 시작해야합니다.
그럼 JVM이 새 스레드를 생성해 운영 체제에게 전달합니다.
스레드 클래스에는 유용한 메서드가 몇가지 있습니다.
예를 들어, start 메서드를 호출 전에 log line을 추가해 현재 실행중인 스레드를 출력하려면 thread.currentThread라는 정적 메서드를 호출해 현재 스레드의 스레드 객체를 알아내야합니다. 스레드 객체를 얻으면 getName메서드나 getId 메서드를 사용할 수 있는데 getName을 사용하겠습니다.
스레드 클래스에는 sleep 메서드라는 정적 메서드도 있습니다. 아시겠지만, 이 메서드는 현재 스레드를 주어진 밀리초 만큼 멈추게 합니다.
이건 반복되는 명령문이 아닙니다. sleep 메서드는 운영 체제에게 지시하는것 뿐입니다. 이 시간이 지날때까지는 현제 스레드를 스케줄링을 하지말라는거죠, 이 스레드는 이 시간 동안 cpu를 쓰지 않는겁니다.
이제 run 메서드에 코드를 추가해 새 스레드에서 실행해 볼게요.
밑에 사진에서 처럼 main이라는 이름의 스레드 객체가 반환됐습니다. 메인 스레드가 실행되었다는거죠 그리고 start 메서드를 호출한 뒤의 새 스레드는 스케줄링 되지 않았어요 시간이 걸리니깐요 운영 체제에 의해 비동기적으로 발생하죠!
따라서 두 번째 출력문도 main 스레드 입니다. 그 후에 thread-0 이라는 새 스레드 코드가 실행되어 반환이 된거죠.
이 스레드 생성 방법을 통해서 생성법을 알았으니 스레드 클래스를 이용한 응용 기능들을 배워 봅시다.
우선 JVM 이 새 스레드에 Thread-0 이라는 쓸모 없는 이름이 붙었었죠????
현재 는 괜찮을지도 모르지만 스레드 개수가 많은 어플리케이션을 만들었을때는 스레드의 의미 있는 이름이 추후 디버깅에 큰 도움이 될겁니다.
스레드 이름을 설정하기 위해 thread.setName 메서드를 호출해 new worker thread 라고 붙이고 어플리케이션을 다시 실행하면 이렇게 새 이름이 콘솔에 출력되게 됩니다.
이전 lecture에서 운영체제가 각 스레드에 동적 우선순위를 적용하는 방법을 배웠습니다. 따라서 스레드 객체를 사용하면 동적 우선순위의 정적 요소를 계획적으로 설정할수 있습니다. setPriority 메서드를 호출해 1부터 10까지의 값을 주거나 사전 정의된 값인 maxPriority, minPriority 아니면 normPriority도 쓸수 있습니다. 전 maxPriority를 사용하겠습니다.
설정을 유효화하기 위해 새 스레드에 출력 제어문을 더해 우선순위가 설정됐음을 명시합니다. 그러려면 현제 스레드 객체에 getPriroity 메세드를 호출해야합니다. 이제 스레드의 우선순위를 봅시다.
MAX priroty를 사용했지만 동작에는 차이가 없습니다. 하지만 복잡한 프로그램의 스레드가 보다 많은 응답성을 필요로 하면 아주 중요한 역할을 합니다.
이제 IDE에서 멀티스레드 애플리케이션을 시각적으로 디버그해 볼게요.
"before start a new thread" 전에 첫 중단점이 뜹니다.
디버그 창으로 가서 스레드 탭을 열면 현재 JVM에서 실행 중인 모든 스레드와 스택 추적을 확인할수 있습니다.
또, 현재 실행중인 메인 스레드와 JVM 이 생성한 새게의 스레드는 당정 제어할 수 없다는것도 확인이 가능합니다.
이대로 계속해서 다음 중단점으로 보면 493이라는 ID이라는 "new worker thread"가 실행중인것을 알수 있습니다.
메인 스레드와 "new worker thread"가 동시에 실행되고 있는걸 알수 있습니다.
breakerPointer = 중단점)
중단점을 지정할 때마다 모든 스레드가 동결되고 개별적으로 검사할 수 있다는 뜻입니다.
새 스레드에 다른 중담점을 추가한 후 계혹한다면 메인스레드는 이미 완료됐고 JVM이 파기했다는걸 알수있습니다.
보통 Java 에서 체크되지 않은 예외는 우리가 직접 캐치해서 특정 방법으로 처리하지 않으면 전체 스레드를 다운시킵니다.
thread.setUncauhtExceptionHandler();
위에 구문을 통해서 처음부터 전체 스데르에 해당되는 예외 핸들러를 지정할 수 있습니다.
스레드 내에서 발생한 예외가 어디서도 캐치되지 않으면 핸들러가 호출될 겁니다. 그러면 우리는 채키되지 않은 스레드와
예외를 출력하기만 하면됩니다. 하지만 더 현실적으로 리소스 일부를 정리한다거나 추가 데이터를 로그하면 문제가 발생한 이후에 우리가 해결할 수 있습니다. 이를 구현하기 위해 스레드에 적절한 이름을 붙이고 RuntimeException을 내부 메시지와 throw 합니다.
이대로 프로그램을 실행하면 Misbehaving thread에서 Intentional Exception이라는 에러 메시지가 발생했다고 뜹니다.
'lecture > Java 멀티스레딩, 병행성 및 성능 최적화' 카테고리의 다른 글
애플리케이션에서 여러 개의 스레드를 사용하는 이유? (0) | 2023.08.17 |
---|---|
lecture 1. 스레딩 기초 (3) | 2023.08.17 |