JAVA

스레드 생성과 실행 - Runnable

silver-w 2024. 10. 23. 22:21

1. Runnable 인터페이스


    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + ": main() start");

        HelloRunnable runnable = new HelloRunnable();
        Thread thread = new Thread(runnable);
        thread.start();

        System.out.println(Thread.currentThread().getName() + ": main() end");
    }

   static class HelloRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+ " : run()");
        }
    }

- 스레드가 실행할 작업을 Runnable 인터페이스를 상속받아 run() 메서드를 오버라이딩

- 메인 스레드에서 Runnable을 구현한 인스턴스를 생성하고, Thread 생성자의 인수로 전달

- 스레드와 작업을 분리하고, thread를 상속하는 것이 아닌, runnable을 구현하므로 유연성이 증가

 

2. Runnable 인스턴스를 여러 스레드에서 실행하면?


    public static void main(String[] args) {
        log("main() start");

        HelloRunnable runnable = new HelloRunnable();

        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(runnable);
            thread.start();
        }

        log("main() end");
    }

스레드100개 + 메인스레드와 전부 별개로 작업이 실행된다.
스레드100개는 전부 스택프레임이 각각 할당받고, 힙영역에는 같은 인스턴스를 작업한다.

< 스택프레임은 101개, 힙 영역에는 인스턴스 1개 >

main thread와 thread-01 ~ 100 run()의 순서는 전부 별개의 작업으로 실행되기 때문에 보장받지 않는다. 

 

3. 중첩 클래스로 스레드 실행


(1) 중첩 클래스 

public class InnerRunnableMainV1 {

    public static void main(String[] args) {
        log("main() start");

        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();

        log("main() end");
    }

    static class MyRunnable implements Runnable {

        @Override
        public void run() {
            log("run()");
        }
    }
}

 

(2) 익명 클래스 

// 익명클래스
public class InnerRunnableMainV3 {

    public static void main(String[] args) {
        log("main() start");

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                log("run()");
            }
        });
        thread.start();

        log("main() end");
    }

}

// rambda 사용
public class InnerRunnableMainV4 {

    public static void main(String[] args) {
        log("main() start");

        Thread thread = new Thread(() -> log("run()"));
        thread.start();

        log("main() end");
    }

}

 

 

4. 스레드가 실행할 작업을 생성자로 만들기


public class StartTest2Main {

    public static void main(String[] args) {
        Thread threadA = new Thread(new printWork("a", 1000));
        Thread threadB = new Thread(new printWork("b", 500));

        threadA.start();
        threadB.start();
    }

    static class printWork implements Runnable {
        private String content;
        private int sleepMs;

        public printWork(String content, int sleepMs) {
            this.content = content;
            this.sleepMs = sleepMs;
        }

        @Override
        public void run() {
            while(true) {
                log(content);

                try {
                    Thread.sleep(sleepMs);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

 

printWork 중첩클래스처럼 스레드의 변수 (content와 sleepMs)를 생성자에 담고 실행하는 run 메서드에 해당 변수들이 어떻게 작동하는지 설계


출처 : https://inf.run/NC7kS

 

김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성 강의 | 김영한 - 인프런

김영한 | 멀티스레드와 동시성을 기초부터 실무 레벨까지 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을 안다?

www.inflearn.com