ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] 스레드, 멀티스레드에 대하여 알아보자.
    Just do it. 2020. 4. 15. 14:18
    반응형

    오늘은 멀티스레드에 대하여 알아보자.


    공부하시는데 참조가 되길바라며 github에 올린 예제소스를 공유드립니다.

    https://github.com/egjeon/thread-basic-example

     

    1. Java 프로그램은 하나의 프로세스로 만들어져 수행된다. 

     

    2. 프로세스는 실행 중인 프로그램.

     

    3. 하나의 프로세스 내부에서 여러 스레드가 실행될 수 있음

     

    4. 스레드는 실행 중인 프로그램 내에 존재하는 소규모 실행 흐름.

     - 스레드는 경량 프로세스

     

     

    멀티스레드

     

    •  Java 프로그램은 하나의 스레드(main thread)로 시작된다.
    •  main 스레드에서 자식 스레드를 만들어 시작시킬 수 있음.
    •  그러면 여러 스레드가 동시에 독립적으로 실행된다.

     

    멀티스레드의 경우 밑에 보이는 두 번째 그림(다중 스레드 프로그램)을 참조하면 이해가 쉽다.

     

     

    단일 스레드 프로그램

     

    다중 스레드 프로그램

     

     

     

    Thread 클래스

     

    • 스레드의 생성과 관리를 위한 메서드를 제공
    •  스레드 생성을 위해 Thread 유형의 객체가 필요하다.

     

    생성자

    • Thread( ) , Thread(String name)
    • Thread(Runnable target)

           Thread(Runnable target, String name)

           Runnable 인터페이스를 구현하려면 run( ) 메서드를 오버 라이딩해야 함

     

     

     

    스레드 생성과 실행

     

    •  스레드 유형의 객체 t를 생성 
    •  t.start( )를 호출하면 스레드 실행이 시작됨
    •  이것은 run( ) 메서드를 호출함
    •  void run ( ) 눈에는 보이지 않지만 실행코드가 있다.

     

     

    *  JAVA에서 Thread 객체를 생성하는 방법 

     

    1. Thread 클래스를 상속받는다.

     

    여기서 run( ) 메서드를 재정의 A 유형의 객체를 생성하고 시작시킨다.

       ex) class A extend Thread

           public void run( ){} 

     

     

     

    2. Runnable 인터페이스를 구현한다.

     

    Runnable 인터페이스를 구현하는 B클래스를 정의한다.

    여기서 Runnable 인터페이스를 Implements 받으면 강제로 run 메서드를 오버 라이딩하여야 한다.

    스레드 객체를 생성할 때 , B유형의 객체를 인자로 전달

    ex) class B implements Runnable

           @Override

            public void run( ){}

     

     

     

     

     

    스레드 실행

     

    •  다중 스레드 프로그램의 실행 결과를 예측할 수 없음
    •  실행 결과는 매번 다를 수 있음
    •  각 스레드는 정해진 순서 없이 독립적으로 실행됨
    •  main 스레드는 다른 스레드와 무관하게 종료됨

     

    스레드의 상태

     

    •  보통 1개의 CPU를 사용하여 여러 스레드가 수행된다.
    • CPU를 얻어 실행되고 최종적으로 종료될 때까지의 여러 상태변화를 겪는다.

     

    아래의 표를 참조하여 보자.

    상태 설명
    Startable 객체가 생성되었으나, start( )의 실행전
    Runnable   start( ) 메소드가 호출되었으나 CPU 획득전
    Running CPU를 얻어 실행중인 상태
    NotRunning CPU를 잃고 중단된 상태 (Blocked,Wating,Timed_wating)
    Dead run( ) 메소드가 종료된 상태

     

    표만으로 이해가 안 될 수 있다 아래의 그림으로 흐름을 파악하여보자.

     

    스레드의 상태 흐름도를 나타낸 표 

     

     

     

    스레드의 상태 제어를 위한 Thread 클래스의 메서드

     

    • void setPriority(int newPriority)

       - 스레드의 우선순위를 변경, 높은 우선순위를 가지는 스레드가 CPU를 얻을 확률이 높음

     

    • static void sleep(long millis) throws InterruptedException

      - 현재 실행 중인 스레드가 정해진 시간 동안 실행을 멈추고

         Not Running 상태로 들어감

     

    • static void yield( ) 

       - 현재 실행 중인 스레드가 잠시 실행을 멈추고 Runnable 상태로 들어감 CPU를 다른 스레드에게 양보하는 것

     

    • void join( ) throws InterruptedException

      - 스레드가 종료될 때까지 기다린다.

      - 현재 실행 중이었던 스레드는 NotRunning 상태로 들어감

     

    • void interrupt( ) 

     - 스레드를 인터럽트 시킴 (간섭함 , 잠든 스레드를 깨울 때 사용)

     - 스레드가 wait( ) , join( ) , sleep( ) 메서드에 의해 중단된 상태였다면 , intterupt메서드를 호출하게 된다면

       그 상태에서 깨어나 Runnable 상태가 됨

     

     

     

    스레드 상태 제어를 위한 Object 클래스의 메서드

     

    • void wait( ) throws InterruptedException
    • void wait(long millis) throws InterruptException
    1.  객체를 처리 중인 스레드를 정해진 시간 동안 중지 시킴
    2.  다른 스레드가 해당 객체에 대해 notify( ) 메서드를 실행시켜주면 이 스레드가 깨어날 수 있음
    3.  이 메서드는 synchronized 메서드의 내부에서만 호출 가능

     

    이 위와 짝꿍? 이 되는 메서드.

     

    •   void notify( ) 
    1.   wait( )을 호출하여 중단된 스레드를 깨워줌
    2.   이 메서드는 synchronized 메서드의 내부에서만 호출 가능

     

    스레드의 간섭

     

    여러 개의 스레드들이 하나의 공유 객체에 동시 접근하는 경우 일관성이 깨지게 된다.

    공유 객체를 동시 접근하게 되는 경우 일관성이 흐트러지는 것에 대한 아래에 그림을 보고 이해해보자.

     

     

    위와 같은 상황을 방지하기 위하여, 밑을 참조하길 바란다.

     

    스레드 동기화

     

    •  서로 다른 스레드들이 공유자원을 다룰 때, 일관성을 유지하도록 하는 것
    •  한 번에 오직 한 개의 스레드만이 해당 공유 객체에 접근하도록 동기화함

     

    방법

    •  상호 배제 원칙
    •  키워드 synchronized
    1.     동기화 메서드 또는 동기화 블록을 제공
    2.     공유 자원을 수정할 때 , 다른 스레드에서 같은 코드를 수행할 수 없게 함

     

    synchronized 메서드

     

    •  한 번에 하나의 스레드에 의해서만 실행 가능
    •  synchronized 메서드를 수행하려면 메서드를 호출한 객체에 대한 lock을 얻어야 함
    •   다른 스레드는 동일 객체에 대해 synchronized 메서드를 실행할 수 없게 됨

    - public synchronized void func( ) {... }

       접근제어자 부분과  synchronized 선언 부과 뒤바뀌어도 상관없다.

     ex) synchronized public void func( ) {... }

     

    일부 블록만 동기화하는 것도 가능함 

     

     synchronized(객체) {... }

        - 객체의 공유 자원으로는 대개 this 

          ex) synchronized(this) {... }

             

     

    많이 부족한 설명이고, 스스로 공부해야 할 부분도 많지만 그래도 어느 정도는 이해가 되었다.

    그림도 가져다 쓰고, 참조하였다 라고 하려다 스스로 그려보면서 모자라지만, 그리다 보면서 좀 더 머릿속으로 더 와 닿았던 것 같다. 

     

     

     

    반응형

    댓글

Designed by Tistory.