Learn/KH정보교육원

[KH정보교육원 당산] 16일차 ( Thread )

Dahoon06 2021. 3. 31. 17:21
728x90
반응형

스레드(Thread)

프로그램을 실행 할 때 운영체제로부터 필요한 메모리를 할당받아 실행한다.(프로세스)

멀티 태스킹 => 2가지 이상의 작업을 할당된 메모리를 가지고 작업을 처리(병렬 처리)

메인 메소드만 실행할 경우 (직렬 처리)

 

스레드를 사용하기 위해서는 Thread를 상속받거나 Runnable을 구현 받아야한다!!

 

사용하는 이유 : 1. 업무 분산

                     2. 처리속도를 높히기 위해서

- 주 스레드 -

Main 스레드

 

- 부 스레드 -

Thread 클래스

Runnable 클래스

 


Main Thread

메인 메소드를 실행 시키면 주 스레드가 실행(메인메소드) 

필요에 따라 부스레드를 실행시켜 여러 작업을 한다.

 

1.ThreadClass 실행

 

ThreadClass 실행

 

2.Runnable 실행

 

Runnable 실행

Runnable은 Thread를 상속받는게 아니기 때문에 start()메소드를 사용할 수 없다.

그렇기에 Thread 객체를 생성하여 이쪽으로 값을 넘겨줘야 사용 가능하다. 

Thread 클래스

=> 반드시 상속을 통해 받음

Thread를 상속 받았기 때문에 run() 메소드를 사용할 수 있다.

 

Runnable 클래스

=>Runnable를 구현받아 재정의 해야한다

 

 

Thread메소드를 스스로 사용하지 못하는데도 사용하는 이유는 Java에서는 상속이 단일 상속 밖에 되지않는다.

 

하지만 구현을 통하여 다중 상속이 가능하기 때문에 여러 스레드를 만들수 있게 된다!!


Thread 주요 메소드

메소드 설명
Thread.start( ) 스레드 시작
Thread.currentThread() 현재 무슨 스레드를 사용하고 있는지 확인
(스레드 객체 반환)
Thread.setName("이름") 사용할 이름을 지정
Thread.getName() 스레드의 이름을 가져온다.
Thread.sleep(밀리초) 스레드의 실행을 초만큼 멈췄다가 실행
Thread.setPriority 우선 순위 부여
Thread.join() 다른스레드가 실행이 끝날때까지 기다렸다가 실행

setPriority() => setPriority(MAX_PRIORTY); // 10

                    setPriority(NORM_PRIORTY);  //5

                    setPriority(MIN_PRIORTY);  // 1

상수를 사용하기 싫으면 1 ~ 10 사이 정수를 사용한다.

 

Main

ThreadName 클래스 처럼 내부에 추가생성자를 만들어서 스레드를 실행 시킬 수 있고 그 이외에 기본생성자로도 스레드를 실행시킬 수 있다.

 

SleepThread클래스에 join 메소드를 사용하여 Main스레드RunnableTest 스레드의 실행을 늦췄다.

 

sleep메소드 활용

반드시 예외처리!! (InterruptedException)

 

출력값

메인 메소드가 실행되면서 내부 코드들을 실행하게 되는데 join메소드를 발견하고 SleepThread의 스레드가 끝날때까지 다른 스레드 멈춤. 

SleepThread 스레드는 sleep메소드를 통해서 5초 정지후 다시 실행.

SleepThread 끝나고 나서 다른 하나의 스레드를 실행 시키고 끝이 나면 또 다른 스레드 실행 

join을 빼면 다른 스레드가 끝나던말던 다 실행됨

 


동기화(Synchronization)

  1. 멀티스레드와 문제점

  2. 공유자원의 접근

  3. synchronized

 

1. 멀티스레드와 문제점

가정) 공항 출입국에 A, B, C 세 사람이 있다.

검색대가 3개 있을 경우에는 문제될 것이 없지만,

검색대가 하나 (공유 자원[Shared Resource]) 밖에 없을 경우에는,

한 사람이 사용하면, 다른 사람들은 검색대을 밖에서 대기.

 

동기화(Synchronization)의 정의

줄서기(번갈아 가면서 순서대로 공유자원 사용하는 것)

동기화(Synchronization)의 기법

synchronization 블록(자원을 사용할 때 자원에 Lock을 거는 방식)

wait()와 notify()

 

2. 공유자원의 접근

공유자원이 문제가 되는 이유

동시에 작업을 진행하는 스레드의 특성 때문

 

Bank 클래스

public class Bank{

               //…

           }

 

NotSynMain 클래스의 스태틱 멤버

public class NotSynMain{

        public static Bank MyBank = new Bank();

        //….작업

            }

 

Me 스레드 클래스

public class Me extends Thread{

        public void run(){

        NotSyncMain.myBank 사용

          } 

    }

 

Wife 스레드 클래스

public class Wife extends Thread{

        public void run(){

        NotSyncMain.myBank 사용

                }

        }

 

두 개의 스레드가 다음과 같이 동시에 실행된다면 공유자원의 문제가 발생

스레드의 생성 및 실행

Me m = new Me(); //Me 스레드 생성

Wife w = new Wife(); //Wife 스레드 생성

 

m.start(); //스레드 시작     

w.start(); //스레드 시작

동기화가 유지되지 않은 경우 입출금의 계산 절차

=>  Me가 10000을 읽어감

=>  Me는 3초 대기 (내부에 sleep메소드를 통하여)

Me가 대기하는 동안 Wife 또한 10000을 읽어감

Me가 대기하는 동안 Wife는 0.2초 대기

Me가 대기하는 동안 Wife는 1000원을 출금

Me가 대기하는 동안 Wife는 작업 완료(남은 돈은 9000원)

Me는 3초 대기한 후 읽어온 10000으로 3000원 입금

결과는 13000원

 

동기화의 유지(synchronized)

Me가 Bank myBank를 사용할 때,

Wife는 Bank myBank를 사용하기 위해서 대기해야 함.

 

결과 12000원(정상적으로 나옴)

 


3. synchronized

메소드블록 형태로 사용할 수 있다.

 

메소드 선언부에 synchronized

public synchronized void saveMoney(int save){

          //....공유자원 - 멤버의 사용

        }      //  해당 메소드 내에서 사용되는 모든 멤버 변수들은 락(Lock)이 걸리게 된다.

 

특정 부분을 synchronized

public void saveMoney(int save){

        synchronized(this){ // this 즉 현재 클래스의 멤버 변수들에 대한 동기화 보장.

          //....공유자원 - 멤버의 사용

              }

         }

synchronized 메소드나 블록 내에서 사용되는 공유자원은 무조건 동기화가 보장.

 

this => 저 위치에는 동기화할 메소드를 보유한 객체의 값이 들어간다

 

메소드 내에 공유자원이 존재하면 this(자기자신)을 주는것이고 만약 다른곳에 위치한다면 값이 존재하는 곳으로 지정 해주면된다.

728x90
반응형