ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java 기초] 멀티 스레드 - 1
    개발언어/Java 2019. 5. 13. 20:44

    1. 멀티스레드란?

     

     스레드(thread)는 본래 '실 가닥'을 뜻하는 용어이다. Java에서는 이것을 '한 가지 작업을 실행하기 위해 순차적으로 실행할 코드를 실처럼 이어놓은 것'을 말한다. 즉, 스레드를 사용하면 여러개의 작업에 스레드를 줘서 스레드를 가진 작업들은 동시에 일을 처리할 수 있게 해주는 기법을 의미한다.

     

    2. 작업스레드의 생성/실행

     작업스레드는 Thread 클래스로부터 직접 생성하는 방법과 Thread 하위 클래스로부터 생성하는 두 가지 방법이 존재한다.

     

    1) 직접생성

    Thread는 java.lang.Thread 클래스를 통해 생성할 수 있는데, 작업 스레드 객체를 만들기 위해서는 아래 코드처럼 Runnable을 매개변수로 받는 생성자를 호출해야한다. 

    Thread t1 = new Thread(Runnable run);

    Runnable은 이름 뜻 그대로 작업스레드가 실행할 수 있는 코드를 가진 인터페이스 객체이다. 따라서, Runnable을 사용하기 위해서는 run 함수를 구현해주어야 하며, 이것에는 3가지 방법이 존재한다.(개인적으로 Java8의 람다를 사용하는 것을 추천한다)

     

    [Runnable 구조]

    class exam implements Runnable {
    	public void run() {
        	// 스레드 실행영역
        }
    }

     

    [방법1. Runnable 객체 생성 후 사용]

    Runnable task = new Task();
    Thread thread = new Thread(task);

    [방법2. thread 생성자 내에서 객체생성]

    Thread thread = new Thread(new Runnable() {
    	public void run() {
        	//스레드가 실행할 코드
        }
    });

    [방법3. Java8의 람다 사용(추천)]

    Thread thread = new Thread(()->{
    	// 스레드가 실행할 코드
    }

     

    작업스레드를 생성했다면, 

    thread.start();

    위의 코드를 통해 실행할 수 있다.

     

     

    2) Thread 하위 클래스로부터 생성

     

    [방법1. Thread 상속 후 run 메서드 오버라이드]

    public class ThreadTest extends Thread {
        @Override
        public void run() {
        	//스레드가 실행할 코드
        }
    }
    Thread thread = new ThreadTest();

    [방법2. Thread 생성자에 run 메서드 선언]

    Thread thread = new Thread() {
    	public void run() {
        	// 실행영역
       	}
    };
    
    thread.start();

     

    참고) thread의 이름

    thread.setName("설정할 이름"); //thread에 고유 이름 생성
    thread.getName(); // thread의 이름 가져오기

     

    3. 스레드 우선순위

     

    1) 우선순위 방식

     우선순위가 높은 스레드가 실행상태를 더 많이 가지도록 스케줄링하는 것.

    thread.setPriority(우선순위값);
    
    thread.setPriority(Thread.MAX_PRIORITY); // 우선순위를 10으로 줌. 즉, 우선순위가 가장 높음
    thread.setPriority(Thread.MIN_PRIORITY); // 우선순위를 5로 줌.
    thread.setPriority(Thread.NORM_PRIORITY); // 우선순위를 1로 줌.
    
    // 단, 아무런 우선순위도 설정하지 않는다면, 자동으로 NORM_PRIORITY가 적용됨.

     

    우선순위 방식에서 주의할 점은 CPU 코어 갯수보다 많은 스레드를 실행시켜야 우선순위를 받는다.(즉, 듀얼코어라면 최소 3개 스레드 이상 사용해야 효과를 볼 수 있음.)

     

    2) 순환할당 방식

     실행시간을 고정하여 정해진 시간만큼 스레드를 번갈아가며 실행시키는 방식을 의미한다. 즉, 타이머를 설정해서 설정된 시간만큼만 실행시키는 방식.

     

     

    4. 동기화 메소드와 동기화 블록

     

    1) 공유객체

     DB에서 트랜잭션에 대해 배웠다면, 공유객체에 대해 이해하기 쉬울 것 같다. 공유 객체란, 어떤 두 스레드가 공유하는 객체를 의미하는데, 하나의 객체에 두 개 이상의 스레드가 접근해서 사용하는 것을 의미한다. 이 경우에는 특정 스레드가 공유객체의 값을 변화시키면 다른 객체에 영향을 미칠 수 있다. 따라서, 서로 독립적인 객체가 되어야하는 경우 객체를 동기화시켜야 한다.

     

    2) 동기화 메소드 및 동기화 블록

     위의 문제를 해결하는 방법은 간단하다. synchronized를 붙여서 해결하면 된다. 즉, 서로 다른 스레드가 하나의 객체를 공유는 하되 공유객체는 한 번에 하나의 스레드가 사용하고, 사용이 끝나면 공유객체를 반납한 후 다른 스레드가 사용할 수 있게 하는 것이다.

     

    public void method() {
    	//여러 스레드가 실행 가능한 영역
        
        synchronized(공유객체 입력) {
        	//여기가 바로 임계영역!(하나의 스레드만 실행가능)
        }
        //여러 스레드가 실행 가능한 영역
        ...
    }

     

    5. 스레드 상태

    <스레드 상태 구조도>

    [표1. 스레드 상태표]

    상태 열거상수 설명
    객체 생성 NEW 스레드 객체생성
    실행 대기 RUNNABLE 실행 대기
    일시정지 WAITING 다른 스레드가 사용해도 된다고 말해주길 기다리는 상태
    TIMED_WAITING 주어진 시간동안 기다리는 상태
    BLOCKED 사용중인 객체의 락이 풀리길 기다림
    종료 TERMINATED 실행 끝

    참고) suspend()는 스레드의 안전성을 해칠 수 있기 떄문에 더 이상 쓰이지 않는다.

     

    [표2. 상태제어표]

    메서드명 설명
    interrupt() 일시정지 상태인 스레드에서 InterruptedException 예외를 발생시켜, catch에서 실행대기상태 또는 종료상태로 갈 수 있게 한다.

    notify()

    notifyAll()

    wait() 에 의해 일시정지한 스레드를 실행대기상태로 만듦

    sleep(long millis)

    sleep(long millis, int nanos)

    주어진 시간동안 일시정지 상태로 만듦.

    join()

    join(long millis)

    join(long miliis, int nanos)

    join() 메소드를 호출한 스레드는 일시 정지 상태가 됨. 실행 대기 상태로 가려면, join()을 멤버로 가지는 스레드가 종료되거나, 매개값으로 주어진 시간이 지나야함.

    wait()

    wait(long millis)

    wait(long miliis, int nanos)

     동기화(Synchronized) 블록 내에서 스레드를 일시정지상태로 만듬.

    yield()

    실행중에 우선순위가 동일한 다른 스레드에게 실행 양보하고 실행 대기 상태가 됨.

     

     

    '개발언어 > Java' 카테고리의 다른 글

    Java Exception  (0) 2020.03.16
    예외 처리  (0) 2020.03.15
    [Java 기초] Stream - 1  (0) 2019.05.26
    [번역] Java 8의 동시성(Concurrency)  (0) 2019.05.01
Designed by Tistory.