프로세스와 스레드
프로세스와 스레드 ( Process & Thread)
프로세스
프로세스란 컴퓨터에서 연속적으로 실행되는 컴퓨터 프로그램이다. 메모리에서 올라와 실행되고 있는 프로그램의 개체 ( 인스턴스 ) 이다. 운영체제로부터 시스템의 자원을 할당받는 작업의 단위이기도 하다.
프로세스의 특징
- 프로세스는 별도의 공간에서 실행된다. 프로세스는 다른 프로세스의 변수나 자료구조에 접근 불가능하다.
- 프로세스는 독립된 메모리 영역을 할당 받는다 ( Coad, Heap, Stack, Data )
- 프로세스당 최소 1개의 스레드를 가진다.
- 프로세스가 다른 프로세스 자원에 접근하려면 통신을 사용해야 한다.
스레드
프로세스 내에서 실행되는 여러 흐름의 단위이다. 프로세스의 특정한 수행 경로가 되며, 프로세스가 할당받은 자원을 이용하는 실행의 단위이다.
스레드의 특징
- 스레드는 한 프로세스 내에 동작되는 여러 실행의 흐름으로, 프로세스 내의 주소 공간이나 자원들 같은 프로세스 내에 스레드끼리 공유하면서 실행된다.
- 스레드는 프로세스 내 각 Stack만 따로 할당 받고, Heap, Data, Coad영역은 공유한다.
- 스레드는 별도의 레지스터와 스택을 갖고있지만, 힙 메모리는 서로 읽고 쓸수 있다.
- 한 스레드가 프로세스 자원을 변경하면 , 다른 이웃 스레드도 그 변경한 결과를 즉시 볼수있다.
멀티 프로세스
운영체제에서 할당받은 자신의 메모리를 가지고 실행하기 떄문에, 서로 독립적이다. 즉 하나의 프로세스에서 오류가 발생해도 다른 프로세스에게 영향을 미치지 않는다.
멀티 스레드
하나의 프로세스 내부에 생성 되기에 하나의 스레드가 예외를 발생시키면 프로세스 자체가 종료될수 있음. 다른 스레드에게 영향을 미친다. 그렇기에 멀티스레드에서는 예외 처리에 주의해야한다.
멀티 프로세스보다 멀티 스레드를 사용하는 이유
프로그램을 여러개 실행시키는 멀티 프로세스
하나의 프로그램 안에서 여러 작업을 하는 멀티 스레드
자원의 효율성 증대
멀티 프로세스로 실행되는 작업을 멀티 스레드로 실행할 경우, 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적메인 스레드
스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.
처리 비용 감소 및 응답 시간 단축
또한 프로세스 간의 통신보다 스레드 간의 통신의 비용이 적으므로 작업들 간의 통신의 부담이 줄어든다.
프로세스 간의 전환 속도보다 스레드 간의 전환 속도가 빠르다. 메
메인스레드
모든 자바 애플리케이션은 메인 스레드가 main() 메서드를 실행하면서 시작되고, return문을 통해 종료된다.
메인스레드는 필요에 따라 스레드를 만들어서 병렬로 코드를 실행할수 있는데, 멀티 스레드를 생성해서 멀티 태스킹을 수행한다.
데몬스레드
데몬 스레드는 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드이다. 주 스레드가 종료되면 데몬스레드는 강제적으로 자동 종료된다. 이 점을 제외하면 일반 스레드와 크게 차이는 없다.
스레드를 데몬으로 만들기 위해서는 주 스레드가 데몬이 될 스레드의 setDaemon(true)를 호출하면 된다.
스레드의 우선순위
멀티 스레드는 동시성 ( Concurrency ) 또는 병렬성 ( Parallelism ) 으로 실행된다.
동시성이란 멀티작업을 위해 하나의 코어에서 멀티스레드가 번갈아가며 실행하는 성질이다.
병렬성은 멀티작업을 위헤서 멀티코어에서 개별스레드를 동시에 실행하는 성질을 말한다.
스레드의 개수가 코어의 수보다 많을 경우 스레드를 어떤 순서에 의해 동시성으로 실행할것인가를 결정하는데, 이것을 스레드 스케쥴링 이라고 한다.
자바의 스레드 스케쥴링은 우선순위 ( Priority ) 방식과 순환 할당 ( Round-Robin ) 방식을 사용한다.
우선순위 방식은 우선순위가 높은 스레드가 실행상태를 더 많이 갖도록 스케쥴링 하는것이고, 순환할당 방식은 시간할당량을 정해서 하나의 스레드를 정해진 시간만큼 실행하고, 다시 다른 스레드를 실행하는 방식을 말한다. 스레드 우선순위 방식은 객체에 우선순위를 부여할수 있기에 개발자가 코드로 제어할수 있지만, 순환할당은 제어가 불가능하다.
스레드의 상태
스레드의 객체 생성 → NEW → 스레드 객체가 생성, 아직 start()메서드가 호출되지 않은 상태
실행 대기 → RUNNABLE → 실행상태로 언제든 갈수 있는 상태
일시 정지 → WAITING → 다른 스레드가 통지할때까지 기다리는 상태
→ `TIMED_WAITING` → 주어진 시간동안 기다리는 상태
→ `BLOCKED` → 사용하고자 하는 개체의 락이 풀릴떄까지 기다리는 상태
종료 → TERMINATED → 실행을 마친상태
스레드 풀
병렬 작업처리가 많아지면 스레드의 개수가 증가되고 그에따른 스레드의 생성과 스케쥴링으로 인하여 CPU가 과열되어 메모리 사용량이 늘어나 애플리케이션 성능이 저하된다. 갑작스런 작업으로 스레드 폭증을 막으려면 스레드 풀을 사용해야 한다.
스레드 풀은 작업처리에 사용되는 스레드를 제한된 개수만큼 정해놓고 작업 큐에 들어오는 작업들을 하나씩 스레드가 맡아 처리한다.
작업처리가 끝난 스레드는 다시 작업큐에서 새로운 작업을 가져와 처리한다. 그렇기 때문에 처리요층이 폭증되어도 스레드의 전체개수가 늘어나지 않으므로 애플리케이션 성능이 급격히 저하되지 않는다. 스레드 풀의 ExecutorService 구현 객체는 Executors 클래스의 다음 두가지 메서드들 중 하나를 이용해서 간편하게 생성가능하다. newCachedThreadPool() , newFixedThreadPool