본문 바로가기

Java

Live Study _ 10주차. 멀티쓰레드 프로그래밍

<학습 목표>

1. Thread 클래스와 Runnable 인터페이스

2. Thread의 상태

3. Thread의 우선순위

4. Main Thread

5. 동기화

6. 데드락 


Thread를 알기 전에! Process 와 Thread :

 

- Process는 운영체제에서 실행 중인 하나의 애플리케이션을 뜻한다. 
  운영체제로부터 실행에 필요한 메모리를 할당받아 애플리케이션의 코드를 실행하는데 이것이 Process이다. 

  그리고 하나의 애플리케이션은 다중 프로세스를 만들기도 한다.

  예를 들어 Chrome 브라우저를 2개 실행하면 2개의 Chrome 프로세스가 생성된 것이다.  

 

- Thread 란 한 가지 작업을 실행하기 위해 순차적으로 실행할 코드를 놓것이다. 

  하나의 스레드는 하나의 코드 실행 흐름이기 때문에 한 프로세스 내에 스레드가 두 개라면 두 개의 코드 실행 흐름이

  생긴다는 의미다. 

 

- Multi Process & Multi Thread 
  Multi Process가 애플리케이션 단위의 Multi Tasking이라면 Multi Thread는애플리케이션내부에서의

  멀티 태스킹이라고 볼 수 있다. 

  Multi Process들은 운영체제에서 할당받은 자신의 메모리를 가지고 실행하기 때문에 서로 독립적이다. 

  따라서 하나의 프로세스에서 오류가 발생해도 다른 프로세스에게 영향을 미치지 않는다. 

 

  Multi Thread는 하나의 프로세스 내부에 생성되기 때문에 하나의 스레드가 예외를 발생시키면 프로세스 자체가

  종료될 수 있어 다른 스레드에게 영향을 미치게 된다. 


1. Thread 클래스 / Runnable 인터페이스 :

 

java.lang.Thread 클래스로부터 작업 스레드 객체를 직접 생성하려면 Runnable을 매개값으로 갖는 생성자를 호출해야 한다. 

예) Thread thread = new Thread(Runnable target); 

 

Runnable은 스레드가 실행할 수 있는 코드를 가지고 있는 객체라고 해서 붙여진 이름이다. 

Runnable은 인터페이스 타입이기 때문에 구현 객체를 만들어 대입해야 한다. 

Runnable에는 run() 메소드 하나가 정의되어 있는데, 구현 클래스는 run()을 반드시 재정의해서 스레드가 

실행할 코드를 작성해야 한다. 

예) class Task implements Runnable{

          public void run() {

               스레드가 실행할 코드; //(동시에 실행 할 작업1 코드를 작성)

         }

     }

 

Thread 사용 3가지 방법 : 

 

기본 방법 :

main thread 
Runnable 객체 만듦

첫 번째 방법은 task객체를 thread class가지고 객체 만들고 매개 값으로 task 객체를 넣어주었다. 

그래서 thread가 task를 실핼하고 task는 작업1을 run() 메소드에 있는 코드를 실행하게 된다. 

 

익명 구현 방법 :

두 번째 방법은 직접 매개 값에 다가 Runnable 인터페이스 구현 객체 만들면서 run() 메소드에 코드를 작성한다. 

 

람다식 방법 :

람다식

Runnable이 run() 메소드 하나만 가지고 있다. 그래서 Runnable은 함수적인 인터페이스에 해당 되기에 람다식 표현으로 작성이 가능하다. 여기서 Runnable은 ()로 표현되었다. 


2. Thread 상태 :

스레드 객체를 생성하고 start() 메소드를 호출하면 스레드가 바로 실행되는 것처럼 보이지만 사실은 실행 대기 상태가 된다. 

실행 대기 상태(Runnable)는 아직 CPU가 아직 스케줄링이 되지 않아서 실행을 기다리고 있는 상태를 뜻한다. 

그래서 스레드 스케줄링으로 선택된 스레드가 CPU를 점유하고 run() 메소드를 실행한다. 그럼으로써 실행상태가 된다. 

실행 상태에서 run() 메소드가 종료되면, 더 이상 실행할 코드가 없기 때문에 스레드의 실행은 멈추게 되고

이 상태를 종료 상태라고 한다. 

 

실행 상태의 스레드는 run() 메소드를 모두 실행하기 전에 스레드 스케줄링에 의해 다시 실행 대기 상태로 돌아갈 수 있다. 그리고 실행 대기 상태에 있는 다른 스레드가 선택되어 실행 상태가 된다. 이렇게 스레드는 실행 대기 상태와 실행 상태를 번갈아가면서 자신의  run() 메소드를 조금씩 실행한다. 

 

경우에 따라서 스레드는 실행 상태에서 실행 대기 상태로 가지 않을 수도 있다. 실행 상태에서 일시 정지 상태로 가기도 하는데, 일시 정지 상태라고 하며 이때는 스레드가 실행할 수 없는 상태이다. 

일시 정지 상태에는 WAITING / TIMED_WAITING / BLOCKED가 있다. 이것은 스레드가 다시 실행 상태로 가기 위해서 일시 정지 상태에서 실행 대기 상태로 가야 되기 때문이다. 

 

Thread 상태 설명


3. Thread 우선수위 :

동시성 & 병렬성

  멀티 스레드는 동시성 혹은 병렬성으로 실행된다. 

  • 동시성 : 멀티 작업을 위해 하나의 코어에서 멀티 스레드가 번갈아 가며 실행하는 성질
  • 병렬성 : 멀티 작업을 위해 멀티 코어에서 개별 스레드를 동시에 실행하는 성질

자바의 스레드 스케줄링은 우선순위 방식과 순환 할당 방식을 사용한다. 

우선순위 -> 우선순위가 높은 스레드가 실행 상태를 더 많이 가지도록 스케줄링하는 것이다. 

 

예) thread.setPriority(우선순위); 

우선순위 매개값으로 1~10까지 값을 직접 설정할 수 있고 Thread 클래스의 상수를 사용할 수 있다. 

Thread 클래스 상수 : 

thread.setPriority(Thread.MAX_PRIORITY); 10과 같은 값

thread.setPriority(Thread.NORM_PRIORITY); 5와 같은 값

thread.setPriority(Thread.MIN_PRIORITY); 1과 같은 값

값이 높을 수록 우선순위가 높다. 

 

순환 할당 -> 시간 할당량을 정해서 하나의 스레드를 정해진 시간만큼 실행하고 다시 다른 스레드를 실행하는 방식이다. 

 

스레드 우선순위 방식은 스래드 객체에 우선 순위 번호를 부여할 수 있기 때문에 개발자가 코드로 제어할 수 있다. 

하지만 순환 할당 ㅂ아식은 자바 가상 기계에 의해서 정해지기 때문에 코드로 제어할 수 없다. 


4. Main Thread :

 

모든 자바 애플리케이션은 메인 스레드가 main()메소드를 실행하면서 시작된다. 

JVM에서 생성되는 main Thread가 실행하게 되는 것이다. 

 

메인 스레드는 main() 메소드의 첫 코드부터 아래로 순차적으로 실행하고, main() 메소드의 마지막 코드를 실행하거나

return문을 만나면 실행이 종료된다.


5. 동기화 :

 

- 스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록 스레드 작업이 끝날 때까지 객체에 잠금을 걸어서 

다른 스레드가 사용할 수 없도록 하는 것이다. 

 

- Critical section ->  단 하나의 스레드만 실행할 수 있는 코드 영역을 임계 영역이다. 

  자바는 임계 영역을 지정하기 위해 동기화(synchronized) 메소드와 동기화 블록을 제공한다. 

  스레드가 객체 내부의 동기화 메소드에 들어가면 즉시 객체에 잠금을 걸어 다른 스레드가 임계 영역 코드를 

  실행하지 못하도록 한다. 

 

- 동기화 메소드를 만ㄷ드는 방법은 synchronized 키워드를 붙이면 되는데 인스턴스와 정적 메소드 어디든 가능하다. 


6. DeadLock 교착상태 :

 

- 데드락은 운영체제나 소프트웨어가 자원을 효율적으로 배분하지 못해 프로세스가 멈춰버리는 현상이다. 

- 이러한 상태에서는 프로그램을 강제로 종료하는 방법 뿐이다. 
- 멀티 스레드 프로그래밍 환경에서 서로 다른 스레드가 지속적으로 얻으려고 하면서 충돌이 일어나고 무한 대기 상태에

  빠지게 된다. 

- 이 문제를 예방하기 위해서는 스레드 코드 순서를 조정해주면서 우선순위 혹은 순환 할당으로 스레드가 동시에 많이
  일어나지 않게 하면 된다. 

'Java' 카테고리의 다른 글

Live Study _ 12주차. Annotation  (0) 2021.02.05
Live Study _ 11주차. Enum(열거 타입)  (0) 2021.01.30
Live Study _ 09주차. 예외 처리  (0) 2021.01.16