스레드(thread), 멀티스레드 / 동기, 비동기

kmb·2022년 6월 6일
0

자바

목록 보기
22/31
post-thumbnail

스레드

프로세스 내에서 실행되는 흐름의 단위.

멀티스레드

하나의 프로세스 내에서 2개이상의 스레드가 동시에 작업을 수행하는것.


자바에서 스레드를 생성하는 방법

  1. Runnable 인터페이스를 구현하여 run( ) 메서드를 정의
  2. Thread 클래스로 구현 객체 생성해서 run( ) 메서드를 정의
class SubThread implements Runnable {

    // 자바의 서브스레드
    @Override
    public void run() {

        for(int i=1; i<6; i++) {

            try {
                System.out.println("서브스레드 : " + i);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class ThreadEx01 {

    // 자바의 메인스레드
    public static void main(String[] args) {

        SubThread st = new SubThread();
        Thread t1 = new Thread(st);  // 타겟 선정
        t1.start();  // run() 메서드 실행

        for(int i=1; i<6; i++) {

            try {
                System.out.println("메인스레드 : " + i);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

코드 실행 순서

  1. 자바를 처음 실행하면 메인스레드 1개만 가지고있는 main( ) 메서드가 실행된다.

  2. SubThread 클래스의 객체(st)를 생성한다.

  3. Thread 객체(t1)를 생성하고 그 안에 타겟(st)을 선정하면 run( ) 메서드가 호출되고 run 스레드가 생성된다.

이때 start( ) 메서드를 호출했는데 왜 run( ) 메소드가 호출된것일까?

--> start( ) 메서드 내부에 start0( ) 메서드가 있고

    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

start0( ) 메서드 내부에는 run( ) 메서드를 호출하도록 구현되어 있다.

    private native void start0();

    /**
     * If this thread was constructed using a separate
     * {@code Runnable} run object, then that
     * {@code Runnable} object's {@code run} method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of {@code Thread} should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

run( ) 메서드 내의 for문이 시작되면 끝날때까지 기다리지않고 문맥교환(Context switching)을 통해서 main( ) 메서드 내의 for문도 실행시킨다.

따라서 결과를 보면 서브 스레드, 메인 스레드가 동시에 실행 되는것을 확인 할 수있다.

자바 어플리케이션은 프로세스가 존재하지않고 메인스레드 밖에 없기 때문에 필요에 따라 작업스레드를 만들어서 메인스레드와 작업스레드를 동시에 병렬로 실행시킬수도 있다.


동기

일의 순서가 있다. (메인 스레드인 CPU가 다른 메인스레드에게 일을 시키고 그 일이 끝날때까지 CPU는 대기 상태에 있다)

비동기

일의 순서가 없다. (메인 스레드인 CPU가 다른 스레드에게 일을 시키고 메인 스레드인 CPU는 계속해서 일을 한다)

1. 싱글스레드 - 동기

작업요청이 여러개 들어왔을때 1개의 스레드가 요청이 들어온 순서대로 1개의 요청에 대한 결과를 처리하고 나서 그 다음 요청을 처리하는것.

ex) 우체국 1개가 여러 손님을 처리. 손님1이 우체국 일을 볼때 손님 2,3,4,...... 는 손님1의 일이 끝날때까지 기다려야한다.

2. 멀티스레드 - 동기

작업요청이 들어온만큼 스레드를 만들어서 처리.
스레드가 작업요청만큼 생기므로 성능 저하 발생.

ex) 우체국을 손님수만큼 만든다. 손님1은 우체국1에서, 손님2는 우체국2에서, ..... 우체국이 너무 많아서 성능 저하 발생.

3. 싱글스레드 - 비동기

작업요청이 여러개 들어왔을때 1개의 스레드가 요청이 들어온 순서에 상관없이 요청을 처리하는것

ex) 우체국은 1개이지만 손님1~손님100까지 집에서 기다린다. 우체국은 우편이 도착하면 손님에게 알려주고 그때와서 손님이 우체국에 와서 일을 처리.

4. 멀티스레드 - 비동기

작업요청이 여러개 들어왔을때 몇개정도의 스레드를 만들어서 비동기로 처리하는것.

ex) 싱글스레드 - 비동기 방식의 우체국을 대략 몇개정도만 만든다음 각 우체국들이 비동기 방식으로 처리하는것.

출처

profile
꾸준하게

0개의 댓글