본문 바로가기
개발공부/JAVA

Thread

by 양히◡̈ 2023. 5. 24.

프로세스

  • 프로그램을 실행하면 운영체제는 이 프로그램이 구동되도록 메모리와 컴퓨터의 입출력 장치, 네트워크 장치 등의 자원을 할당해서 프로그램을 실행하는데, 이때 실행되는 이 프로그램을 프로세스라고 함
  • 구성
    • 프로그램에 사용되는 데이터와 메모리 등의 자원, 그리고 스레드로 구성
    • 프로그래밍된 프로그램의 흐름으로 프래그램을 실행

스레드(Thread)

  • 프로그램은 하나의 일을 처리할 수 있도록 하나의 흐름을 가지고 프로그램이 실행되는데 이런 흐름을 스레드라고 함
  • 스레드를 여러 개 두어 프로그램을 실행하는 것을 멀티 스레드라고 함
  • 프로그램 개발
    • 일반적으로 프로그램은 단일 흐름을 가지는 싱글 스레드 방식으로 프로그램을 개발함
    • 하지만 최근 다양한 플랫폼에서 동작 프로그램들은 성능을 높이기 위해 멀티 스레드로 프로그램을 개발하고 있음
  • 멀티 프로세스는 각 프로세스가 독립적인 메모리를 가지고 별도로 실행되는 것이며, 멀티 스레드는 각 스레드가 자신이 속한 프로세스의 메모리를 공유함
  • 모든 프로세스에는 한 개 이상의 스레드가 존재하고 이 스레드에 의해 프로그램을 실행함
  • 멀티스레드
    • 멀티 스레드는 프로그램의 성능을 높이거나 사용자와의 인터랙션을 향상시킨 등 자원을 효율적으로 운영하기 위해 사용함
    • 하지만 멀티 스레드의 사용이 모든 처리의 성능을 향상시키는 것은 아님
    • 멀티프로세싱에서 다른 프로세스로 전환하려면 레지스터, 메모리, 업데이트 목록 등을 저장하고 로드하는 처리 시간이 필요하나 멀티스레딩은 스레드 간 통신시 처리되는 시간이 짧음
  • 스레드의 실행 시점
    • 어떤 스레드를 실행할 것인가의 결정은 프로그래머가 아닌 JVM이 제어
    • 한 번에 하나의 스레드의 처리만 가능하기 때문에 특정 스레드가 특정 시점에 실행하는 것을 완벽하게 보장할 수 없음
    • JVM에서 스레드를 선택하는 방식
      • Runnable 상태의 스레드들 중에 우선순위가 높은 작업을 먼저 선택해서 실행함
      • JVM이 스레드들 중 선택할 때 참고하는 것일 뿐 우선수위가 높은 스레드가 먼저 완료되는 것이 아님
  • 스레드의 생명주기
    1. NEW
      • Thread 클래스로 인스턴스가 생성된 상태로, 아직 start() 메소드를 호출하지 않아 새로운 작업의 흐름이 생성되기 전의 상태
    2. Runnable
      • 스레드 인스턴스의 start() 메소드가 호출된 후 실행 가능한 상태
      • 인스턴스를 JVM의 스케줄러가 스레드를 실행 가능한 리스트에 올려놓은 상태라고 할 수 있음 (실행 중인 상태가 아님)
    3. Running
      • JVM의 스레드 스케줄러가 스레드 인스턴스를 선택하고, 스레드가 실행 중인 상태
    4. Non-Runnable(Blocked)
      • 스레드 인스턴스가 소멸된 상태는 아니지만 실행이 가능하지 않은 상태를 의미
      • 보통은 이 상태에서 실행 가능 상태로 변경하여 처리함
      • sleep(), suspend(), wait() 메소드가 실행되었을 때 Non-Runnable 상태가 됨
      • Non-Runnable 상태에서 다시 Runnable 상태로 변경할 때는 sleep()이 실행 완료되거나, resume(), notify() or notifyAll() 메소드를 사용함
    5. Terminated
      • 스레드 인스턴스를 사용하지 못하는 상태
      • 보통은 스레드 인스턴스의 run() 메소드의 처리 명령이 모두 정상적으로 실행되어 종료되는 상태
      • 사용자에 의해 스레드가 강제 종료되는 경우(stop() 메소드)

스레드의 실행 구조

  • Thread 클래스
  • 생성자
    • Thread() : 기본적인 스레드를 생성
    • Thread(String name) : 전달된 문자열의 이름으로 스레드를 생성
    • Thread(Runnable r) : Runnable 인터페이스를 구현한 인스턴스로 스레드를 생성
    • Thread(Runnable r, String name) : 전달된 문자열과 Runnable 인터페이스를 구현한 인스턴스로 스레드를 생성
  • 주요 메소드
    • start() : 스레드 실행(실행 흐름)을 시작
    • run() : 스레드에 대한 처리 부분을 수행
    • sleep() : 매개변수로 전달되는 시간 동안 스레드를 휴면 상태로 만듦
      • 이 메소드를 사용할 때는 InterrunptedException 예외처리를 반드시 해야함
    • join() : 스레드가 종료되기를 기다림
      • 현재 수행중인 스레드가 작업을 완료할 때까지 현재 실행 중인 다른 스레드의 실행이 중지됨
      • join() 메소드가 실행되는 스레드를 제외한 나머지 스레드의 상태가 blocked 상태로 되는 것
    • getPriority()/setPriority() : 스레드의 우선순위를 반환/설정
    • suspend()/resume() : 스레드를 일시 중지/재개
    • wait() : 다른 스레드가 이 스레드 인스턴스에 대해 notify()나 notifyAll() 메소드를 호출하거나 지정된 시간이 경과할 때까지 기다림
    • notify()/notifyAll() : 대기중인 스레드를 깨움
    • stop() : 스레드를 종료시킴
  • Runnable 클래스
    • 스레드 인스턴스 생성시 필요한 타입 (다중상속)
    • 스레드 인스턴스 생성을 위해서 Runnable 클래스를 반드시 구현하는 인스턴스가 필요
    • 추상 메소드인 run() 메소드 하나만을 정의하고 있음
  • 스레드 실행 순서
    • Thread 클래스를 상속하고, run() 메소드를 Overrride함
    • Thread 인스턴스 생성 후 start() 메소드 실행 (Runnable 상태)
  • 하나의 인스턴스는 start()를 한 번만 호출할 수 있음(IllegalException)
  • 스레드의 메모리 구조
    • 스레드가 생성될 때 스레드마다 stack 영역을 가지게 됨
    • 각각의 스레드는 heap 영역과 method 영역의 변수를 공유할 수 있음

스레드의 동기화 처리

  • JAVA의 동기화 : 멀티 스레드의 처리 중에 자원의 공유 시에 스레드의 자원에 대한 액세스를 제어하는 기능
  • 목적
    • 동기화 처리를 하지 않는다면 자원의 일관성을 유지할 수 없기 때문에 동기화를 반드시 해야함 (데이터 일관성 유지 목적)
  • 개념
    • 기본적으로 특정 인스턴스의 변수에 액세스해야 하는 스레드는 인스턴스에 액세스하기 전에 인스턴스의 Lock을 획득하여 Lock을 해제한 다음 변수에 액세스하게됨
  • 방법
    • 메소드에 Lock을 걸어주는 동기화 메소드 정의 방법
      • 동기화가 필요한 변수를 가지는 메소드 앞에 synchronized 키워드를 붙임
    • 동기화가 필요한 해당 부분만을 Lock 처리해주는 동기화 블록 처리방법
      • synchronized 키워드를 붙이고 나서 동기화가 필요한 블록을 중괄호로 묶음
        synchronized(object 참조변수) {
          //code block
        }

댓글