(Ch13) 4.싱글쓰레드와 멀티쓰레드 ~

8. 쓰레드의 실행제어

싱글쓰레드보다 멀티쓰레드가 더 좋을까?

두 작업을 처리하는 상황에서 싱글쓰레드의 경우 한 작업을 마친 후 다른 작업을 시작하지만, 멀티쓰레드는 2개의 쓰레드가 번갈아 가면서 작업을 수행하기 때문에 동시에 작업이 수행되는 것처럼 보인다. 하지만 오히려 멀티쓰레드의 경우가 시간이 더 걸릴 수 있는데, 이는 쓰레드간 작업 전환에 시간이 걸리기 때문이다. 작업 전환은 다음에 실행해야할 위치 등의 정보를 저장하고 읽는 시간이 필요하다. 그래서 싱글 코어에서 단순히 CPU만 사용하는 계산작업의 경우에는 싱글쓰레드가 더 효율적이다.

만약 두 쓰레드가 서로 다른 자원을 사용하는 작업의 경우에는 멀티쓰레드가 더 효율적이다. 예를 들어 사용자로부터 입력값을 받는 작업, 네트워크로 파일을 교환하는 작업, 프린터로 파일을 출력하는 작업과 같이 외부기기와 상호작용을 해야하는 경우가 이에 해당한다.

쓰레드의 우선순위는 어떻게 정할까?

쓰레드에는 우선순위라는 속성이 존재한다. 이 우선순위 값에 따라 쓰레드가 얻는 실행시간이 달라진다. 대부분 시각적인 부분이나 사용자에게 빠르게 반응해야 하는 작업에 우선순위를 높게 부여하여 처리해야 사용자의 만족도를 이끌어 낼 수 있을 것이다.

쓰레드가 가질 수 있는 우선순위의 범위는 1에서 10사이이며, main메소드를 수행하는 쓰레드는 우선순위가 5이고, main 메소드 내에서 생성되는 모든 쓰레드의 우선순위는 5가 된다.

실제로 우선순위를 다르게 부여해도 멀티코어에서는 차이가 거의 발생하지 않는다. 멀티코어의 경우 우선순위가 높은 쓰레드가 더 많은 실행시간과 기회를 갖게 될 것이라고 기대할 수 없다. OS마다 쓰레드의 스케쥴링 방식이 달라 이를 고려할 수도 있지만, 어느 정도 예측만 가능한 수준이라 큰 의미가 없다. 차라리 쓰레드에 우선순위를 두는 것보다 작업에 우선순위를 두어 우선순위가 높은 작업이 먼저 처리되도록 하는 것이 더 나을 수 있다.

쓰레드 그룹이란 무엇인가?

쓰레드 그룹이란 연관된 쓰레드를 그룹으로 묶어 다루기 위해 존재하는 개념이다. 쓰레드 그룹을 다른 그룹에도 포함될 수 있으며, 보안상의 이유로 도입된 개념이다. 자신이 속한 쓰레드 그룹이나 하위 쓰레드 그룹은 변경할 수 있지만, 다른 쓰레드 그룹의 쓰레드를 변경할 수는 없다.

모든 쓰레드는 쓰레드 그룹에 포함되어 있어야 하고, 특정 그룹을 지정하지 않은 쓰레드는 자신을 생성한 쓰레드와 같은 그룹에 속하게 된다. JVM이 실행되면 크게 main과 system이라는 쓰레드 그룹을 만든다. 우리가 만드는 모든 쓰레드 그룹은 main 쓰레드 그룹의 하위 그룹이 된다.

데몬 쓰레드란?

데몬 쓰레드는 일반 쓰레드의 작업을 돕는 보조적인 역할을 수행하는 쓰레드이다. 그렇기에 일반 쓰레드가 종료되면 데몬 쓰레드 역시 강제 종료된다. 데몬 쓰레드는 무한루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 작업대기 상태가 된다. 데몬 쓰레드는 쓰레드를 생성한 다음 setDaemon(true)를 호출하기만 하면 된다. 데몬 쓰레드의 예시로는 가비지 컬렉터, 워드프로세서의 자동저장, 화면자동갱신 등이 있다.

쓰레드의 실행제어는 어떻게 이루어질까?

쓰레드 프로그래밍이 어려운 이유는 동기화와 스케줄링 때문이다. 우선순위를 통해 스케줄링 하는 방법을 보았지만 근본적인 해결책이 될 수 없음을 확인했다. 효율적인 멀티쓰레드 프로그램을 위해서는 정교한 스케줄링을 통해 자원과 시간의 낭비를 막아야 한다.

쓰레드의 상태는 여러가지 종류가 있다.

NEW : 쓰레드가 생성되고 start()되지 않은 상태
RUNNABLE : 실행 중 혹은 실행 가능한 상태
BLOCKED : 동기화블록에 의해 일시정지된 상태
WAITING, TIMED_WATING : 작업이 종료되진 않았지만 실행 가능하지 않은 일시정지 상태.
TERMINATED : 작업이 종료된 상태

다음은 쓰레드의 동작을 제어하는 메소드에 대해 알아보자.

sleep(long millis) - ()안에 있는 시간(단위 : 밀리세컨드)동안 쓰레드를 멈추게 한다.
interrupt()와 interrupted() - 쓰레드의 작업을 취소한다.
suspend(),resume(),stop() - 쓰레드를 멈추게하고, 실행대기 상태로 만들고, 즉시 종료시키게 하는 메소드. 현재는 deprecated되어 사용해서는 안된다.
yield() - 다른 쓰레드에게 자신이 할당 받은 자원을 양보한다.
join() - 작업을 멈추고 다른 쓰레드의 작업이 수행되도록 한다.

Reference

Java의 정석
남궁성의 정석코딩

profile
개발자 지망생입니다.

0개의 댓글