본문 바로가기

수업 정리

17일차 수업 정리(Thread)

Tip!

스마트폰의 특징
  - 업그레이드가 불가(기기를 바꿀때까지)
  - 언제 네트워크가 끊어질지 알수없음


Thread 생성
    - 상호 배제 => Lock으로 해결
    - 생산자와 소비자
    - Dead Lock
    - Semaphore ex) 은행 번호표

**Thread
    => 프로세스 내에 만드는 것으로 작업 도중 다른 작업으로 제어권을 넘길수 있도록 해주는 작업단위
    => 단독으로는 실행할 수 없고, 프로세스(Method)내에서 생성하여 실행
    => 일반 메소드 호출은 한 메소드의 수행이 완료될때까지 타 메소드의 수행을 할 수 없는 구조
    => 스레드는 하나의 작업이 진행중인 동안에도 제어권을 다른 스레드로 옮겨서 처리가 가능
    => 스레드를 만드는 방식은 대다수의 프로그래밍 언어가 유사하고, 해결해야할 문제도 유사함
    => synchronized(동기식) : 순서대로 처리, asynchronized(비동기식) : 순서를 알수 없음

1. 생성
  1) java.lang.Thread 클래스 이용
    => Thread 클래스로부터 상속받는 클래스를 만들어서 run메소드를 구현
    => 클래스의 인스턴스를 생성해서 start()를 호출
    => Thread 클래스에는 run 메소드 이외의 여러 메소드가 존재

  2) java.lang.Runnable 인터페이스를 이용
    => Runnable 인터페이스를 구현한 클래스를 만들어서 run메소드를 구현
    => 클래스의 인스턴스를 생성
    => Thread 클래스의 인스턴스를 생성할 때 생성자의 매개변수로 만들어진 인스턴스를 대입
    => Thread 클래스의 인스턴스가 run을 호출
    => Runnable 인터페이스에는 run메소드만 존재

2. Java에서 상속이나 구현하는 방법
  1) 상속이나 구현한 클래스를 만들고 인스턴스를 생성
  2) 클래스를 만들지 않고 상속이나 구현한 인스턴스를 생성 - anonymous Class

3. Daemon Thread
    => DaemonThread가 아닌 스레드가 없으면 자동으로 종료되는 스레드
    => 백그라운드에서 작업하고 있다가 다른 스레드가 종료되면 같이 종료되는 스레드
    => 주기적으로 계속해서 해야하는 작업중 자동으로 종료되면 좋을 것 같은 작업을 만들 때 사용
       ex) 응용프로그램에서 주기적으로 하는 자동 저장, 서버와 클라이언트 시스템의 데이터 백업등에 주로 이용
    => 생성 : start를 호출하기 전에 setDeamon(true)를 호출

4. Thread Priority(우선순위)
    => 스레드의 우선 순위 설정 가능
    => 우선 순위 설정시 스레드의 시작 순서나 동작횟수를 서로 다르게 설정가능
    => getpriority 메소드를 이용하여 우선 순위를 정수로 리턴받고, setPriority로 우선순위 설정 가능
    => 우선 순위가 높다고 반드시 먼저 수행되거나 자주 수행되는 것은 아님(확률이 더 높음)
    => 우선순위 설정시 매개변수는 정수지만 정수를 직접 설정하는 것은 좋지 않음
        - Thread 클래스의 Field를 이용하는 것을 권장
        - Thread.MAX_PRIORITY, Thread.NORMAL_PRIORITY, Thread.MIN_PRIORITY등으로 설정
          -> MS Windows 스레드의 우선순위는 1~10, 리눅스는 1~7(10설정시 Linux에서는 비적용, MAX시 10 or 7 적용)

5. ThreadGroup
    => 여러개의 스레드를 묶어주기 위해서 제공하는 클래스
    => 리눅스에서 제대로 동작하지 않는 경우가 있어 실제 사용은 잘 하지 않음
    => List를 이용하여 직접 묶어서 사용

6. 스레드의 강제 종료
  1) Interrupt : 다른 작업을 방해하는 것
    => 작업 별로 우선 순위라는 것이 있어서 우선 순위가 높은 작업이 발생시킨 인터럽트만 전달
  2) 강제종료
    => 스레드의 실행 구문에서 InterrupteException이 발생하면 return 하도록 코드를 작성
    => 스레드 인스턴스가 interrupt()라는 메소드를 호출하도록 하면 됨
  3) 되도록이면 스레드를 만들때 IntteruptedException이 발생하면 종료하도록 작성하는 것이 좋음
    => 스마트폰의 경우 InterruptedException 발생시 현재 상태를 저장 후, 해결되면 이어서 하도록 작성

7. Mutual Exclusion(상호배제)
    => 하나의 스레드가 사용중인 자원의 사용을 끝내기 전에 다른 스레드가 수정할 수 없도록 하는 것
    => Critical Section(임계영역) : 공유자원을 사용하는 코드영역
  1) Synchronized Method
    => 메소드의 결과형 앞에 synchronized를 붙여주면 이 메소드는 수행중에 다른 스레드에게 제어권 이전 X
        But. 메소드를 sychronized화 하면 공유도가 떨어짐
  2) Synchronized block
    => 공유 자원을 한번에 사용해야 하는 코드 영역을 synchronized(공유객체){ }로 묶는 것
        - { }안의 코드 영역 실행시 다른 스레드가 공유 객체를 사용할 수 없도록 함
  3) ReentrantLock을 이용
    => 인스턴스를 만들고 lock()을 호출하면 동기화 블럭이 되고 unlock()을 호출하면 해제

8. 생산자와 소비자 문제
    => 생산자 스레드는 자원을 생산, 소비자 스레드는 자원을 소비하는 경우 동시에 수행할수 있도록 제작 가능
        (생산자가 자원 미생산 상태에서 소비자가 자원을 소비하려고 할 경우 예외가 발생(소비자 스레드 종료 현상 발생)
    => 공유자원이 없을 경우 소비자 스레드가 중지상태에 있다가 생산자가 자원 생성 후 신호시 작업 수행하도록 제작
    => 작업 대기 : wait 메소드 호출, 신호 전송 : notify()와 notifyAll()을 이용
        - notify() : wait 중인 스레드 중 하나를 실행
        - notifyAll() : wait 중인 모든 스레드를 실행시키는 것
    => wait 메소드와 notify 메소드는 

9. Semaphore
    => 동시에 수행할 스레드의 개수를 설정할 수 있는 클래스
    => ThreadPool : 여러개의 스레드를 *미리 만들어두고* 빌려서 사용할 수 있도록 해주는 스레드의 집합
    => ThreadPool은 데이터베이스나 웹 서버에서 많이 사용하는데 Semaphore를 이용해서 구현 가능

**연습문제
{20, 19, 76, 87, 22} : 거리가 가장 가까운 2개의 숫자 조합을 찾아내서 출력

Tip
오버헤드 - 순수하게 작업하는 시간을 제외한 모든 시간

mutable Data : 변경 가능한(Variable)
immutable Data : 변경 불가능한(Constant)