JAVA) 스레드
Computer Science/Java

JAVA) 스레드

인하대학교 임광수 교수님 수업과 자료 참고

 

#프로세스란?

 : 실행중인 프로그램으로, 디스크에 있는 프로그램이 메모리에 적재되어 운영체제의 제어를 받는 상태이다.

 : 자신만의 자원을 가지기 때문에 프로세스 끼리는 서로 독립적으로 작동한다.( 프로세스끼리는 정보를 주고받을 수가 없다._=)

  => 서로 다른 프로세스 간에 데이터를 공유할 때 어떻게 할수 있을지가 이슈로 작용하게 된다.

 

# 멀티태스킹

 : 대부분의 운영체제는 시스템 자원을 효율적으로 사용할 수 있도록 멀티태스킹을 지원한다.

 :멀티코어 cpu라면 실제로 다수의 애플리케이션을 동시에 병렬처리하고, 싱글코어라면 다수의 애플리케이션을 병행처리한다. (멀티 프로세싱/ 멀티 스레드 두가지가 있다.)

=> 심지어 하나의 애플리케이션에서도 동시에 수행할 수 있는 다수의 코드 블록이 있을수 있기 때문에 멀티태스킹이 가능하다 => 이를 멀티스레딩이라고 하고, 효율적으로 프로그램이 돌아가도록 한다.

 

#스레드란?

하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업 단위를 말하며, 세부적으로는 운영체제에 의해 관리되는 하나의 작업 또는 태스크를 의미한다. => 스레드와 태스크를 바꾸어 사용해도 무방한다.

=> 하나의 실행 흐름으로, 프로세스 내부에 존재하게 된다.

=> 프로세스는 적어도 하나의 스레드를 가지고 있다.

 : 프로세스에 비해 실행 환경에 필요한 자원이 매우 적기 때문에 경량 프로세스라고 한다.

 

=> 하나의 프로세스가 다수개의 작업을 각각 스레드를 이용하여 동시에 사용할 수 있는 것을  멀티스레드 프로세스라고 한다. : 멀티 프로세스에 비해서 상당한 이점을 가지고 있다. (메모리 손실 줄이고, 모든 메모리를 공유할 수 있다.)

 +) 동시에 두가지 이상 활동을 할 수 있고, 시스템 자원 소모가 줄어들지만

    서로 자원을 소모하다가 충돌이 일어날 수 있고, 코딩이 난해해져 버그 생성 확률이 높아진다.

 

#JVM, 프로세스, 스레드

  : 자바 애플리케이션의 실행 환경인 JVM은 각각 별도의 프로세스로 실행된다.( 스택이나 힙 메모리 영역 공윹)

   : 하나의 스레드가 있는 단일 스레드가 속도가 훨 씬 빠르다.

   1시간에 7개를 하나씩 차근차근 하는것이 1분마다 7개를 바꿔가면서 처리하는 것보다 효율적이기 때문.

   => 멀티스레드/ 단일 스레드의 차이점

  => 자바 애플리케이션은 적어도 메인 스레드라는 하나의 스래드를 가진다.

     : 다수의 스레드로 실행하려면 runnable 인터페이스 또는 Thread 클래스를 상속하는 방법 두가지 중 하나로 작업 

스레드를 별도로 추가해야 한다.

 

   

       => Thread 객체 생성자: Thread t= new Thread(new Runnableclass());

             등으로 안에 runnable 객체를 하나 사용해서 스레드 객체를 생성해주어야 한다.

 

 

            => 이 때, implement이므로 run 하는 메소드를 반드시 오버라이딩 해줘야 한다.

          

            => 또한 따로 runnable 객체를 생성하는 클래스(이름) 없이 무명 객체를 구현할 수도 있다.

       

 

 

 # Thread pool

 : 스레드들을 미리 만들어 놓은 하나의 풀장이라고 생각하면 된다.

  : 요청이 들어올 때마다 스레드를 생성하고 일을 다하면 수거하는 작업은 프로그램 퍼포먼스에 지대한 영향을 줄 수 있다. => 따라서 스레드를 미리 만들어놓아야 한다.

 

  => 만든 어플리케이션에서 사용자로부터 들어온 요청을 작업 큐에 넣고 스레드풀은 작업 큐에 들어온 task들을 미리 만들어 놓은 thread에 할당한다. 작업을 마치면 어플리케이션에게 결과값을 리턴한다.

  

1) 스레드 풀의 장점

  - 프로그램 성능 저하를 방지할 수 있다.

  - 다수의 사용자 요청 (task)들을 처리할 수 있다.

2) 단점

  - 너무 많이 만들어 놓았다가 메모리 낭비만 발생할 수가 있다.  

  - 노는 스레드가 발생할 수가 있다.

   (a,b,c 스레드가 있을때 a한테만 일을 떠맡기고 b,c는 놀고있는 상황이 발생한다.)

 

  +) JDK 5부터 Excecutors 클래스를 포함하는 java.util.concurrent 패키지를 이용해 지원한다.

 

 

 

#스레드 생명 주기

   : JVM은 스레드의 개수, 스레드의 상태, 우선순위 등 스레드와 관련된 모든 정보를 관리하며, 스레드 스케줄링을 수행한다.

 

    1. Runnable-> start() 메소드를 호출하면 run() 메소드에 설정된 스레드가 runnable상태로 진입한다.

    2. Running() -> cpu를 점유하여 실행하고 있는 상태이며, run() 메소드는 JVM 만이 호출 가능하다.

      Runnable 상태에 있는 여러 스레드 중 우선순위를 가진 스레드가 결정되면 JVM이 자동으로 호출하여 

      스레드가 running 상태로 진입한다.

    3. Dead -> 모든 스레드가 종료된 상태.

    4. Blocked-> cpu가 점유권을 상실된 상태. wait() 메소드에 의해 blocked가 되며, notify() 메소드가 호출되면                  runnable 상태가 된다.  sleep()  메소드로 blocked된 스레드는 지정시간 후에 runnable 상태가 된다.

 

 

    # 스레드의 종료

    - run()  메소드 실행 종료를 위한 stop() 메소드 

     -> 호출 즉시 스레드를 종료하므로 사용중인 자원을 낭비할 가능성이 있어서 가급적 사용하지 않는다.

    - 안전한 종료를 위해 반복문, interrupt() 메소드를 사용한다.

 

 

 

 

   => 스레드는 메인이 끝나도 계속 돌아가게 된다.

   하지만 이러한 스레드도 join() 메소드를 이용해 제어할 수 있다.

    -> join()을 이용하면 해당 스레드가 종료되기 기다렸다가 다음으로( main 함수 가 스레드 종료 후에 종료된다.)

 

  +) join 메소드가 없으면 메인 함수가 다 끝난 뒤에 스레드가 돌아가게 된다.

 

# 스레드 우선순위

   -멀티태스킹에서 스레드 개수가 CPU 코어 개수보다 많다면 스레드 스케줄링이 필요하다.

   - 자바에선 우선순위 방식과 순환할당 방식을 사용한다.

 

 

  #데몬 스레드

   : 데몬 스레드란 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드이다.

    =>다른 스레드를 모두 종료하면 자동으로 종료된다.

   ex) 워드 프로세스의 자동 저장, 미디어 플레이어의 동영상 및 음악 재생... etc

 

=> 주 스레드가 종료되면(워드 프로세스, 미디어 플레이어, JVM...) 같이 종료된다.

 => 데몬스레드 아닐 때/ 데몬 스레드일때 두가지 결과가 다르게 나온다.

 

# 스레드 동기화

   : 작업들 사이의 수행 시기를 맞추는 것이다.

   => 사건이 동시에 일어나거나, 일정한 간격을 두고 일어나도록 시간의 간격을 조정한다.

    - 이유: 스레드가 같은 프로세스 내의 자원을 공유하면서 작업하는 경우에 서로의 작업이

     다른 작업에 영향을 주기 때문이다. 

    - 해결 방법: 스레드의 동기화를 위해서 임계영역의 잠금을 사용한다.

     => 임계영역이란? : 병렬 컴퓨팅에서 둘 이상의 스레드가 동시에 접근해서는 안되는 공유자원에 접근하는 코드.

     

     - 동기화 블록에 진입한 스레드가 락이 걸리고, 그 코드를 실행할 동안 다른 스레드는 동기화 블록 앞에서 락이 풀릴때까지 기다려야한다. / 고로 한 스레드 작업을 끝낼때까지 다른 스레드는 실행되지 못한다.

 

  동기화하지 않으면 중간에 다른 스레드가 중구난방으로 들어와서 출력되어버릴 수 있다.

 

 

#대기와 통보

   : 동기화 메소드와 블록을 이용하면 공유 자원은 보호할 수 있지만, 특정 스레드가 필요 없이 오랜 시간 동안 락을 걸수 있다. => object 클래스는 객체의 락과 관련된 wait(), notify(), notifyall() 메소드를 제공하여 이런 상황을 해결할 수 있다. (이 메소드들은 동기화 블록 안에서 사용해야 한다.)

  wait()를 만나면 해당 스레드는 해당 객체의 락 권한을 놓고 대기하며, notify() 메소드를 통해 다음 메소드를 깨운다.

 

 

 # 스레드 협업

 : 자원을 공유하지만 하나는 생산하고, 다른 하나는 소비하는 형태의 작업으로 두 스레드 사이에 협업이 필요하다.

 

 

 

'Computer Science > Java' 카테고리의 다른 글

본격 JVM 해부하기  (0) 2022.11.24
JAVA) 이벤트 구동 프로그래밍  (0) 2019.12.07
Java -GUI 프로그래밍  (0) 2019.12.05
Java) 입출력 스트림- 11주차 수업  (0) 2019.12.03