본문 바로가기

언어공부/Java

자바 멀티쓰레드

자바 멀티쓰레드에 대해서 알아보자.

멀티쓰레드

프로세스(process)는 실행중인 프로그램이다. 프로그램을 실행하면 OS로 부터 실행에 필요한 자원(메모리)을 할당받아 프로세스가 된다. 프로세스는 프로그램을 수행하는 데 필요한 데이터와 메모리 등의 자원 그리고 쓰레드로 구성되어 있으며 프로세스의 자원을 이용해서 실제로 작업을 수행하는 것이 바로 쓰레드이다.

 

그래서 모든 프로세스에는 최소한 하나 이상의 쓰레드가 존재하며, 둘 이상의 쓰레드를 가진 프로세스를 멀티쓰레드 프로세스(Multi-threaded process)라고 한다.

ex) 싱글쓰레드 = 자원+쓰레드 / 멀티쓰레드 = 자원+쓰레드+쓰레드+....

 

멀티쓰레드의 장점은 아래와 같다.

  • CPU의 사용률을 향상시킨다.
  • 자원을 보다 효율적으로 사용할 수 있다.
  • 사용자에 대한 응답성이 향상된다.
  • 작업이 분리되어 코드가 간결해진다.

여러 사용자에게 서비스를 해주는 서버프로그램의 경우 멀티쓰레드로 작성하는 것은 필수적이어서 하나의 서버 프로세스가 여러개의 쓰레드를 생성해서 쓰레드와 사용자의 요청이 일대일로 처리되도록 프로그래밍 해야한다. 만일 싱글쓰레드로 서버 프로그램을 작성한다면 사용자의 요청마다 새로운 프로세스를 생성해야하는데 프로세스를 생성하는 것은 쓰레드를 생성하는 것에 비해 더 많은 시간과 메모리 공간이 필요하기 때문에 많은 수의 사용자 요청을 서비스 하기 어렵다.

 

멀티쓰레드 구현 방법

 

1. Thread 클래스를 상속 받는다.

Thread 클래스를 상속받아 멀티스레드를 구현하면 방법은 쉽지만, 단일 상속만 가능하다는 단점이 있다.

 

 

출력화면

 

2. Runnable 인터페이스를 상속받는 법

다중 상속을 받을 수 있다는 장점이 있다. 하지만 멀티스레드를 시작하는 start()메소드가 없기 때문에 이 인터페이스를 상속받은 자식클래스 객체를 Thread클래스 생성자 인자값으로 넘겨줘서 다시 한번더 객체를 생성해서 start()메소드를 호출해야 한다는 단점이 있다. 

 

멀티스레드에서 start()메소드를 호출하면 멀티스레드가 시작되면서 run()메소드를 자동 호출한다. 명시적인 run()메소드를 호출하지 않아도 start()메소드만 호출하면 run()메소드는 자동 호출하도록 자바는 설계되어져 있다.

 

 

출력화면.

 

실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다. 싱글코어에서 싱글쓰레드와 멀티쓰레드의 프로세스들을 각 비교하면 작업 수행시간은 오히려 멀티쓰레드일 때 더 걸리게 되는데 쓰레드간의 작업전환 시간이 더 걸리기 때문이다.

 

작업전환을 할 때는 현재 진행 중인 작업의 상태, 예를들면 다음에 실행해야할 위치 등의 정보를 저장하고 읽어오는 시간이 소요된다. 참고로 쓰레드의 스위칭 보다 프로세스의 스위칭이 더 많은 정보를 저장해야하므로 더 많은 시간이 소요된다. 그래서 싱글 코어에서 단순히 CPU만을 사용하는 계산작업이라면 오히려 싱글쓰레드로 프로그래밍 하는 것이 더 효율적이다.

 

쓰레드를 실행할 때 마다 쓰레드의 순서는 다르게 나오는데 그 이유는 실행 중인 예제프로그램(프로세스)이 OS의 프로세스 스케줄러의 영향을 받기 때문이다. 자바가 OS(플랫폼)에 독립적이라고 하지만 실제로는 OS종속적인 부분이 몇 가지 있는데 쓰레드가 그 중 하나이다.

 

JVM의 쓰레드 스케쥴러에 의해서 어떤 쓰레드가 얼마동안 실행될 것인지 결정되는 것과 같이 프로세스도 프로세스 스케쥴러에 의해서 실행순서와 실행시간이 결정되기 때문에 매 순간 상황에 따라 프로세스에게 할당되는 실행시간이 일정하지 않고 쓰레드에게 할당되는 시간 역시 일정하지 않게 된다. 그래서 쓰레드가 이러한 불확싱성을 가지고 있다는 것을 염두에 두어야한다.

 

 

쓰레드와 프레임을 이용해서 java라는 글자가 0.1초마다 x+5만큼 이동하는 예제이다. x좌표가 프레임폭을 벗어 나면 다시 x=0으로 처음부터 반복된다.

 

실행화면.