본문 바로가기

Java

[Java] 쓰레드(Thread) 정리

 

프로세스와 쓰레드

 

프로세스 :  독립된 실행 프로그램의 단위

쓰레드 : 독립된 실행 프로그램 안에서의 실행 흐름 (실행 흐름이 1개면 싱글 스레드, 여러 개면 멀티 스레드)

 

모든 프로세스에는 최소한 하나의 쓰레드(main쓰레드)가 존재하게 된다.

쓰레드는 프로세스라는 작업공간에서 작업을 수행하는 일꾼의 역할을 한다.

 

싱글 쓰레드와 멀티 쓰레드

 

싱글 쓰레드 : 하나의 프로세스에서 하나의 쓰레드를 가지고 작업을 수행

멀티 쓰레드 : 하나의 프로세스에서 둘 이상의 쓰레드를 가지고 작업을 수행

 

싱글코어에서는 멀티 쓰레드보다 싱글 쓰레드를 이용하는 것이 더 효과적이다.

싱글코어에서 싱글 쓰레드와 멀티 쓰레드의 작업을 비교해 보면 멀티 쓰레드가 더 작업이 빠르다고 생각할 수 있지만 겨론은 별반 차이가 없거나 오히려 싱글 쓰레드의 작업 처리가 더 빠르다.

그 이유는 멀티 쓰레드는 지속적으로 작업하는 쓰레드를 전환(context switching)해 주어야 하고, 작업을 전환하는데 걸리는 시간이 더 오래 걸리기 때문이다.

반면 멀티코어에서 멀티 쓰레드를 사용할 경우 동시에 두 개의 쓰레드가 작업을 수행할 수 있고, 겹치는 작업 시간이 생기게 되면서 처리 속도가 빨라지고 효율적인 CPU의 사용이 가능해진다.


 

쓰레드 구현

 

쓰레드를 구현하는 방법은 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하면 된다.

자바에서는 다중 상속이 불가능하기 때문에 Thread클래스를 상속받기보다는 Runnable 인터페이스를 구현하는 것이 일반적이다.

Runnable 인터페이스 안에는 run() 추상 메서드가 포함되어 있으며 run() 메서드를 구현해 주면 된다.

Runnable 인터페이스로 구현할 경우 Runnable을 구현한 클래스 객체를 생성한 후 Thread 클래스의 생성자 매개변수에 참조 변수를 넣어 주어야 한다.

위 과정을 통해 쓰레드가 생성되었다면 start() 메서드를 통해 쓰레드를 실행시켜주면 된다.

 

쓰레드 제어 메서드

메서드 내용
static void sleep(long millis) 1/1000초 동안 쓰레드를 일시정지시킨다.
void join() 해당 작업의 수행이 끝날 때까지 기다렸다가 결과를 반환
void interrupt() 일시정지인 상태의 쓰레드를 깨워서 실행상태로 바꿈
void yield() 다른 쓰레드에 주어진 자신에게 주어진 실행시간을 양보하고 실행 대기상태가 됨
void wait() 호출되거나 지정된 시간도안 기다림
void notify() 대기중인 쓰레드에게 통보
  • 예제코드
public class ThreadSum {
    static int sum = 0;

    public static void main(String[] args) {

        Thread t1 = new ThreadSum1();
        Thread t2 = new Thread(new ThreadSum2());

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

class ThreadSum1 extends Thread {

    public void run() {

        for(int i = 1; i <=50; i++) {
            System.out.println(ThreadSum.sum += i);
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }    
 }




class ThreadSum2 implements Runnable {    
    @Override
    public void run() {        
        for(int i = 51; i <=100; i++) {
            System.out.println(ThreadSum.sum += i);
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
      }
  }

 

쓰레드의 동기화

 

동기화 : 요청과 결과가 동시에 일어난다. 요청 후에 결과가 나와야지만 다음 작업을 수행하게 된다.

비동기화 : 요청과 결과가 동시에 일어나지 않는다. 요청 후에 결과에 상관없이 다른 작업을 수행할 수 있게 된다. 

 

Critical Section : 공유 데이터를 사용하면서 쓰레드가 다른 쓰레드로 제어가 넘어가면서 문제가 발생할 수 있는 부분

동기화(Synchronization) : Critical Section 구간에서 다른 쓰레드가 공유 데이터를 사용할 수 없도록 막는 것

 

synchronized 키워드

메서드나 특정 영역에 synchronized 키워드를 명시하고 critical section으로 설정하여 동기화할 수 있다.