[13] 스레드와 멀티테스킹

서희찬·2022년 12월 3일
0
post-thumbnail

멀티태스킹

하나의 프로그램이 여러개의 작업을 동시에 처리

사례

스레드 개념과 실

테트리스 프로그램을 구성하는 멀티스레드 분석

스레드와 멀티스레딩

스레드

  • 사용자가 작성한 코드로서, JVM에 의해 스케줄링되어 실행되는 단위

자바의 멀티태스킹

  • 멀티스레딩만 가능
    • 스레드는 JVM의 의한 실행 단위, 스케쥴링 단위
  • 하나의 응용프로그램은 여러 개의 스레드로 구성 가능

멀티스레딩의 효과

  • 한 스레드가 대기하는 동안 다른 스레드는 실행
  • 프로그램 전체적으로 시간 지연을 줄임

웹 서버의 멀티스레딩 사례

자바 스레드란?

자바 스레드

  • 자바 가상 기계에 의해 스케쥴되는 실행 단위의 코드 블럭
  • 스레드의 생명 주기는 JVM에 의해 관리됨
    • JVM은 스레드 단위로 스케쥴링
  • JVM과 멀티스레드의 관계
    • 하나의 JVM은 하나의 자바 응용프로그램만 실행
      • 자바 응용프로그램이 시작할 때 JVM이 함께 실행됨
      • 종료 하면 함께 종료함
    • 하나의 응용프로그램은 하나 이상의 스레드로 구성 가능

JVM과 자바 응용프로그램, 스레드의 관계

자바 스레드와 JVM

자바에서 스레드 만들기

  • 스레드 실행을 위해 개발자가 하는 작업
    • 코드 작성, 스레드 생성, 스레드 코드 실행 JVM에게 요청
  • 스레드 만드는 2가지 방법
    • java.lang.Thread class
    • jvaa.lang.Runnable interface

Thread 클래스를 이용한 스레드 생성

스레드 클래스, 코드 작성

class TimerThread extends Thread { 
....................................................
@Override
public void run() {
// run() 오버라이딩
......................... }
}
  • run() method 오버라이딩
    • run() method : thread code
    • run() method에서 스레드 실행 시작

스레드 객체 생성

TimerThread th = new TimerThread();

스레드 시작

th.start();
  • start() method 호출
    • 스레드로 작동 시작, JVM에 의해 스케쥴 되기 시작

Thread를 상속받아 1초 단위로 초 시간을 출력하는 TimerThread 작성

예제 13-1 : Thread를 상속받아 1초 단위의 타이머 만들기

스레드 만들 시 주의 사항

  • run() method가 종료하면 스레드는 종료
    • 스레드 계속 살아있게 하려면 run() method 내 무한루프 작성
  • 한번 종료한 스레드는 다시 시작시킬 수 없다.
    • 다시 스레드 객체 생성 하고 start()호출해야 함.
  • 한 스레드에서 다른 스레드를 강제 종료할 수 있다.

Runnable interface로 스레드 만들기

스레드 클래스, 코드 작성

class TimerThread implements Runnable { 
....................................................
@Override
public void run() {
// run() 오버라이딩
......................... }
}
  • run() method 오버라이딩
    • run() method : thread code
    • run() method에서 스레드 실행 시작

스레드 객체 생성

TimerThread th = new TimerThread();

스레드 시작

th.start();

Runnable 인터페이스를 상속받아 1초 단위로 초 시간을 출력하는 스레드 작성

예제 13-2 : Runnable 인터페이스를 이용하여 1초 단위로 출력하는 타이머 스레드 만들기

예제 13-3 : 깜박이는 문자열을 가진 레이블 만 들기


스레드 정보

스레드 상태

스레드 상태 6가지

NEW

  • 스레드가 생성되었지만 스레드가 아직 실행할 준비가 되지 않았음

RUNNABLE

  • 스레드가 현재 실행되고 있거나 실행 준비되어 스케쥴링을 기다리는 상태

WAITING

  • wait()를 호출한 상태(다른 슽레드가 notify() or notifyAll()을 불러주기를 기다리고 있는 상태)
  • 스레드 동기화를 위해 사용

TIMED_WAITING

  • sleep(n)을 호출하여 n 밀리초 동안 잠을 자고 있는 상태

BLOCK

  • 스레드가 I/O 작업을 요청하면 JVM이 자동으로 BLOCK상태로 만듦

TERMINATED

  • 스레드가 종료한 상태
  • 스레드 상태는 JVM에 의해 기록 관리됨

스레드 상태와 생명 주기


=> 매우 중요 암기!!

스레드 우선순위와 스케쥴링

스레드 우선 순위

  • 최대값 = 10(MAX_PRIORITY)
  • 최소값 = 1(MIN_PRIORITY)
  • 보통값 = 5(NORMAL_PRIORITY)

스레드 우선순위는 응용프로그램에서 변경 가능

  • void setPriority(int priority)
  • int getPriority()

main() 스레드의 우선순위 값은 초기에 5

스레드는 부모 스레드와 동일한 우선순위 값을 가지고 탄생

JVM의 스케쥴링 정책

  • 철저한 우선순위 기반
  • 가장 높은 우선순위의 스레드가 우선적으로 스케쥴링
  • 동일한 우선순위의 스레드는 돌아가면서 스케쥴링(라운드 로빈)

main()을 실행하는 main 스레드

main 스레드와 main() 메소드

  • JVM은 응용프로그램을 실행을 시작할 때 스레드 생성 : main 스레드
  • JVM은 main 스레드에게 main() 메소드 실행하도록 함
  • main() 메소드가 종료해도 main 스레드가 종료하지 않을 수도 있음.

예제 13-4 : main 스레드의 정보 출력

스레드 종료와 타 스레드 강제 종료

  • 스스로 종료 : return run() method
  • 타 스레드에서 강제 종료 : interrupt() method 사용

    InterruptedException를 통한 thread 종료 방법

예제 13-5:타이머스레드 강제종료


flag를 이용한 종료

  • 스레드 A가 스레드 B의 flag 를 true로 만들면, 스레드 B 가 스스로 종료하는 방식

예제 13-6 : flag를 이용한 스레드 강제 종료


스레드 동기화

멀티 스레드 프로그램 작성시 주의점

다수의 스레드가 공유 데이터에 동시에 접근하는 경우

  • 공유 데이터의 값에 예상치 못한 결과 발생 가능

스레드 동기화

멀티스레드의 공유 데이터의 동시 접근 문제 해결책

  • 공유 데이터를 접근하는 모든 스레드의 한 줄 세우기
  • 한 스레드가 공유 데이터에 대한 작업을 끝낼 때까지 다른 스레드가 대기 하도록 함
    => 그러니깐 그냥.. 줄서서 기다리고 자기 차례에 쓴다는거임

두 스레드의 프린터 동시 쓰기로 충돌하는 사례

공유 집계판에 동시 접근하는 사례

스레드 동기화 기법

스레드 동기화

  • 공유 데이터에 동시에 접근하는 다수의 스레드가 공유 데이터를 배타적으로 접근하기 위해 상호 협력(coordination)하는 것
  • 동기화의 핵심
    • 스레드의 공유 데이터에 대한 배타적 독점 접근 보장

자바에서 스레드 동기화를 위한 방법

  • synchronized로 동기화 블록 지정
  • wiat()-notify() method로 thread 실행 순서 제어

synchronized 블록 지정

synchronized 키워드

  • 한 스레드가 독점 실행해야 하는 부분(동기화 코드)을 표시하는 키워드
    • 임계 영역(critical section) 표기 키워드
  • 메소드 전체 혹은 코드블록

synchronized 블록에 대한 컴파일러의 처리

  • 먼저 실행한 스레드가 모니터 소유
    • 모니터란 해당 객체를 독점적으로 사용할 수 있는 권한
  • 모니터를 소유한 스레드가 모니터를 내놓을 때까지 다른 스레드 대기

synchronized 사용 예 : 공유 집계판 사례를 코딩

SharedBoard의 add()를 스레드1이 실행하고 있는 동안, 스레드2가 호 출하면 스레드2는 대기

공유집계판 사례에서 synchronized 사용하지 않아 충돌로 인해 데이터에 오류가 발생한 경우

producer-consumer 문제와 동기화

producer-consumer 문제

  • producer : 공유 메모리에 데이터를 공급하는 스레드
  • consumer : 공유 메모리의 데이터를 소비하는 스레드
  • 문제의본질
    • producer와 consumer 가 동시에 공유 데이터를 접근하는 문제

producer-consumer 문제 사례

  • 미디어 플레이어
    - producer:입력스레드, consumer:재생스레드, 공유데이터:비디오버퍼

wait(), notify(), notifyAll()를 이용한 동기화

동기화 객체

  • 두 개 이상의 스레드 동기화에 사용되는 객체

동기화 메소드

  • synchronized 블록/메소드 내에서만 사용되어야 함
  • wait()
    • 다른 스레드가 notify()를 불러줄 때까지 기다린다.
  • notify()
    • wait()를 호출하여 대기중인 스레드를 깨우고 RUNNABLE 상태로 만든다.
    • 2개 이상의 스레드가 대기중이라도 오직 한 스레드만 깨운다.
  • notifyAll()
    • wait()를 호출하여 대기중인 모든 스레드를 깨우고 모두 RUNNABLE 상태로 만든다.

wait(), notify(), notifyAll()은 Object의 메소드

  • 모든 객체가 동기화 객체가 될 수 있다.
  • Thread 객체도 동기화 객체로 사용될 수 있다.

예제 13-6 : wait(), notify()를 이용한 바 채우기

코드

실행결과

profile
Developing For Our Lives, 세상에 기여하는 삶을 살고자 개발하고 있습니다

0개의 댓글