스레드란? 멀티 태스킹(muli-tasking)는 여러 개의 애플리케이션을 동시에 실행하여서 컴퓨터 시스템의 성능을 높이기 위한 기법 그림23-1. 병철 처리의 예
스레드란? 다중 스레딩(multi-threading)은 하나의 프로그램이 동시에 여러 가지 작업을 할 수 있도록 하는 것 그림23-2. 다중 스레드의 개념
프로세스와 스레드 프로세스(process): 자신만의 데이터를 가진다. 스레드(thread): 동일한 데이터를 공유한다. 그림23-3. 스레드는 하나의 프로세스 안에 존재한다.
스레드를 사용하는 이유 웹 브라우저에서 웹 페이지를 보면서 동시에 파일을 다운로드할 수 있도록 한다. 워드 프로세서에서 문서를 편집하면서 동시에 인쇄한다. 게임 프로그램에서는 응답성을 높이기 위하여 많은 스레드를 사용한다. GUI에서는 마우스와 키보드 입력을 다른 스레드를 생성하여 처리한다.
중간 점검 문제
스레드 생성과 실행 스레드는 Thread 클래스가 담당한다. 스레드의 작업은 Thread 클래스의 run() 메소드 안에 기술한다.
스레드 생성과 실행 Thread 클래스를 상속하는 방법 Thread 클래스를 상속받은 후에 run() 메소드를 재정의한다. 스레드 생성 방법 Runnable 인터페이스를 구현하는 방법 run() 메소드를 가지고 있는 클래스를 작성하고 ,이 클래스의 객체를 Thread 클래스의 생성자를 호출할 때 전달한다.
Thread 클래스를 상속하기 Thread를 상속받아서 클래스를 작성한다. run() 메소드를 재정의한다. start()를 호출하여서 스레드를 시작한다. 일수를 알고 싶은 달을 입력하시오:6 월의 날수는 30
Thread 클래스를 상속하기 일수를 알고 싶은 달을 입력하시오:6 월의 날수는 30
Runnable 인터페이스를 구현하는 방법 Thread 객체를 생성하고 이때 MyRunnable 객체를 인수로 전달한다. start()를 호출하여서 스레드를 시작한다.
Runnable 인터페이스를 구현하는 방법
예제 A10 B10 A9 B9 B8 A8 B7 B6 A7 B5 A6 B4 A5 B3 A4 A3 A2 B2 A1 B1 A0 B0
예제#1
예제#1
중간 점검
Thread 클래스
예제: sleep() Pride will have a fall. Power is dangerous unless you have humility. Office changes manners. Empty vessels make the most sound.
인터럽트 인터럽트(interrupt)는 하나의 스레드가 실행하고 있는 작업을 중지하도록 하는 메카니즘이다. 그런데 만약 스레드가 실행 중에 한번도 sleep()을 호출하지 않는다면 InterruptedException를 받지못한다.
조인 join() 메소드는 하나의 스레드가 다른 스레드의 종료를 기다리게 하는 메소드이다.
예제
예제
실행결과 main: 추가적인 스레드를 시작합니다. main: 추가적인 스레드가 끝나기를 기다립니다. Thread-0: Pride will have a fall. Thread-0: Power is dangerous unless you have humility. main: 참을 수 없네요! Thread-0: 아직 끝나지 않았어요! main: 메인 스레드 종료!
스레드의 상태 그림23-4. 스레드이 상태
중간 점검
동기화 동기화(synchronization): 한 번에 하나의 스레드 만이 공유 데이터를 접근할 수 있도록 제어하는 것이 필요
동기화 기법 동기화란 쉽게 설명하면 공유된 자원 중에서 동시에 사용하면 안 되는 자원을 보호하는 도구이다.
스레드 간섭 스레드 간섭(thread interference)이란 서로 다른 스레드에서 실행되는 두 개의 연산이 동일한 데이터에 적용되면서 서로 겹치는 것을 의미 (예) 카운터 하나의 Counter 객체를 두개의 스레드가 공유하면서 카운터 값을 변경한다고 가정하자.
스레드 간섭 만약 스레드 A가 increment()를 호출하고 동시에 스레드 B가 derement(_)를 호출하였다고 가정하자.
문제 발생 다음과 같은 상황을 가정하자. 4개의 스레드가 하나의 카운터를 증가했다가 다시 감소한다.
예제
예제 ... -7 -8
실행결과 ... -7 -8
메모리 불일치 오류 메모리 불일치 오류는 서로 다른 스레드가 동일한 데이터의 값을 서로 다르게 볼 때, 발생한다. 스레드 A가 counter를 다음과 같이 증가하였다. 잠시 후에 스레드 B가 counter의 값을 출력한다.
동기화된 메소드 동기화된 메소드를 만들기 위해서는 synchronized 키워드를 메소드 선언에 붙이면 된다.
실행 결과 1 ...
중간점검 1 ...
스레드간의 조정 만약 두개의 스레드가 데이터를 주고 받는 경우에 발생 그림23-7. 생산자와 소비자 문제
스레드간의 조정 polling Event-driven
스레드 간의 조정 방법
스레드 간의 조정 방법 wait()가 호출되면 스레드는 가지고 있던 락을 해제하고 실행을 일시 중지한다.
wait()와 notify() 그림23-8. wait() notify()
생산자/소비자 문제 생산자는 데이터를 생산하고 소비자는 데이터를 가지고 어떤 작업을 한다. 생산자-소비자 문제에서 중요한 것은 생산자가 생산하기 전에 소비자가 물건을 가져가면 안된다. 반대로 이전 물건을 소비하기 전에 생산하면 안 된다. ☞ 동기화된 메소드를 사용하여 두 개의 스레드가 동시에 버퍼 객체에 접근하는 것을 막는다. 동기 화된 apthsem는 synchronized키워드를 메소드 앞에 붙여서 만든다. ☞ 케익을 생산하고 가져가는 동작을 일치시키기 위하여 두 개의 스레드를 동기화할 수 있는 어떤 방법이 필요하다. 스레드 간의 동작을 일치하기 위하여 사용하는 메소드들이 wait() notify()이다. 이들 메소드를 이용하여 생산이 되었음을 소비자에게 명시적으로 알리고 또 한 소비가 되었음을 명시적으로 생산자에게 알릴 수 있다.
생산자/소비자 문제에 적용 먼저 케익을 임시적으로 보관하는 Buffer 클래스를 작성한다.
생산자/소비자 문제에 적용
생산자/소비자 문제에 적용 그림23-9. 생산자와 소비자 문제
예제 생산자를 코딩하여 보자 이번에는 같은 방식으로 소비자 스레드를 작성한다.
예제 마지막으로 메인 스레드를 작성하여 준다.
실행결과 만약 wait(), notifyall()을 사용하지 않고 무조건 케익을 가져가고 생산한다면 다음과 같이 잘못된 결과가 나온다.
실행결과