[Java] 11. Thread(쓰레드)란?


쓰레드에 대한 포스팅이다.



>

1. 프로세스와 쓰레드

프로세스(process)란? "실행 중인 프로그램(program)"을 말한다. 프로그램을 실행하면 OS로부터 실행에 필요한 자원(메모리)를 할당 받아 프로세스가 된다. 프로세스의 자원을 받아 실제로 작업을 수행하는 것이 바로 쓰레드이다.

그래서 모든 프로세스에는 최소 한개 이상의 쓰레드를 가지고 있으며, 하나의 프로세스에서 2개 이상을 가지는 쓰레드를 멀티쓰레드라고 한다.


대부분의 OS는 멀티태스팅 기능이 있기 때문에 여러 프로세스 동시 실헹되고, 하나의 프로세스에서 여러 쓰레드가 수행되는게 멀티쓰레딩이다. 그래서 PC에서 다른 일(문서작업)을 하면서 파일을 받고 음악을 듣고 가능한 것이다.



1-1. 멀티쓰레드 장단점

1) 장점

  • CPU 의 사용률 향상
  • 시스템 자원을 보다 효율적으로 사용
  • 사요자에 대한 응답성이 향상
  • 작업이 분리되어 코드가 간결


2) 단점

  • 동기화(synchronization)에 주의해야 한다.
  • 교착상태(dead-lock)가 발생하지 않도록 주의해야 한다.
  • 각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야한다.



2. 쓰레드의 구현과 상속 2가지 방법

1 ) Thread 클래스를 상속

class MyThread1 extends Thread {
    //Thread 클래스의 run() 오버라이딩
    public void run() {
        //구현
    }
}

MyThread1 t1 = new MyThread();
t1.start();


2 ) Runnable 인터페이스를 구현

class MyThread2 extends Runnable {
    //Runnable 인터페이스의 추상메서드 run() 구현
    public void run(){
        //구현
    }
}

Runable r = new MyThread2();
Thread t2 = new Thread(r);
t2.start();



3. start() 와 run()

  • start()는 새로운 쓰레드를 생성하면서 호출 스택을 생성한다.(메모리 할당)
  • 새로 호출스택에 run()이 호출되어 새로 쓰레드에서 작업을 수헹한다.
  • 호출스택이 2개이므로 스케줄러가 정한 순서에 의해 번갈아 가면서 실행한다.



4. 싱글쓰레드와 멀티쓰레드

두개의 작업하나의 쓰레드두개의 쓰레드로 처리하는 과정이다. 두개의 쓰레드로 작업을 처리하는 멀티쓰레드는 프로세스를 번갈아 가면서 점유하는 것을 볼 수 있다. 이것을 쓰레드간의 작업 전환(context switching)이라고 하며 전환시 전환하는 시간도 걸리다.


아래 싱글/멀티 쓰레드 결과값과 해당 그림을 보고 다시 이해해는게 좋을 듯 하다.


single-thread&multi-thread-s1


싱글 쓰레드 예제

public class ExNotThread {

    public static void main(String... args) {
        //일반 생성자
        NotThreadEx1 t1 = new NotThreadEx1();
        NotThreadEx2 t2 = new NotThreadEx2();

        //메서드명이 run일뿐 쓰레드를 상속하지 않은 클래스임
        t1.run();
        t2.run();
    }
}

class NotThreadEx1 {

    public void run() {
        for (int i=0; i<20;i++) {
            System.out.print("O");
        }
    }
}

class NotThreadEx2 {
    public void run() {
        for (int i=0; i<20;i++) {
            System.out.print("X");
        }
    }
}

결과

OOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXX



멀티쓰레드 예제

public class ExThread {

    public static void main(String... args) {
        //1. 1. Thread 클래스를 상속 생성 방법
        ThreadEx1 t1 = new ThreadEx1();
        //2. Runnable 인터페이스를 상속 생성 방법
        Runnable r = new ThreadEx2();
        Thread t2 = new Thread(r);

        //3. 쓰레드 실행 (실행 가능상태)
        //- 실행순서는 OS스케쥴러가 정함
        //- 새로운 호출 스택을 생성하고 run 을 위한 스레드를 실행
        t1.start();
        t2.start();
    }
}


//1. Thread 클래스를 상속 받아 쓰레드 구현
class ThreadEx1 extends Thread {
    //Thread 클래스에 run() 메서드를 오버라이딩
    @Override
    public void run() {
        for (int i=0; i<20;i++) {
            //System.out.println(getName());
            System.out.print("O");
        }
    }
}

//2. Runnable 인터페이스를 상솓 받아 쓰레드 구현
class ThreadEx2 implements Runnable {
    //Runnable 인터페이스의 run() 추상메서드를 구현
    @Override
    public void run() {
        for (int i=0; i<20;i++) {
            //Thread.currentThread() 로 현재 실행중인 스레드를 반환한다.
            //System.out.println(Thread.currentThread().getName());
            System.out.print("X");
        }
    }
}

결과

OOOOOOXXXXXXXXXXXOOOOOOOOOOOOOOXXXXXXXXX




[출처]

  • 자바의정석 (저자: 남궁성)