[쓰레드]

hamonjamon·2022년 7월 31일
0
post-custom-banner

| 쓰레드 공유 객체


  • MusicPlayer 3명은 MusicBox를 사용한다.

  • 이는 하나의 객체를 여러 개의 스레드가 사용함을 의미한다.

public class MusicBox {
    public void playMusicA() {
        for (int i = 0; i < 10; i++) {
            System.out.println("드레이크 음악!");

            try {
                Thread.sleep((int) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void playMusicB() {
        for (int i = 0; i < 10; i++) {
            System.out.println("켄트릭 라마 음악!");

            try {
                Thread.sleep((int) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void playMusicC() {
        for (int i = 0; i < 10; i++) {
            System.out.println("제이지 음악!");

            try {
                Thread.sleep((int) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class MusicPlayer extends Thread{
    int type;
    MusicBox musicBox;

    public MusicPlayer(int type, MusicBox musicBox) {
        this.type = type;
        this.musicBox = musicBox;
    }


    @Override
    public void run() {
        switch (type) {
            case 1:
                musicBox.playMusicA();
                break;
            case 2:
                musicBox.playMusicB();
                break;
            case 3:
                musicBox.playMusicC();
                break;
        }
    }
}

public class MusicBoxExam {
    public static void main(String[] args) {
        MusicBox box = new MusicBox();

        MusicPlayer kang = new MusicPlayer(1, box);
        MusicPlayer kim = new MusicPlayer(2, box);
        MusicPlayer yang = new MusicPlayer(3, box);

        kang.start();
        kim.start();
        yang.start();
    }
}

| 공유 객체를 가진 메서드를 동시에 호출하지 않는 방법

  • 해당 메서드 앞에 리턴 타입으로 "synchronized"를 추가한다.

  • 먼저 호출된 메서드에 synchronized 키워드가 있을 경우, 객체의 사용권을 가지며 synchronized가 붙은 다른 쓰레드들은 대기 상태에 놓인다.

  • 참고로 synchronized를 붙이지 않은 메서드는 대기 상태가 아닌, 제멋대로 실행된다.


| 쓰레드와 상태 제어 (join)

  • join() 메서드의 경우 쓰레드가 멈출 때까지 기다린다.
public class MyThred1 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("MyThred1 : " + i);
            try {
                Thread.sleep((int) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThred1 thread = new MyThred1();
        // Thread 시작
        thread.start();
        System.out.println("기다리는 중....");
        try {
            // 대기
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread 종료");
    }
}

| 쓰레드와 상태 제어 (wait, notify)

  • wait, notify는 동기화된 블록 내부에서 사용해야 한다.
public class ThreadB extends Thread {

    int total;

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(i + "를 더하다");
                total += i;

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notify();
        }
    }
}
public class ThreadA {
    public static void main(String[] args) {
        ThreadB threadB = new ThreadB();
        threadB.start();

        synchronized (threadB) {
            try {
                System.out.println("threadB 완료까지 대기");
                threadB.wait(); // notify() 메서드를 만나야 깨어난다.
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("total : " + threadB.total);
        }
    }
}

| 데몬 쓰레드


  • 데몬 : 리눅스, 유닉스 계열의 운영체제에서 백그라운드로 동작하는 프로그램

  • 데몬 쓰레드 : 자바에서 데몬과 유사하게 동작하는 쓰레드

    • 주기적으로 자동 저장 기능, 에디터를 만드는데 일정 시간마다 맞춤법 검사하는 기능 등에 쓰이곤 한다.
    • 주 스레드가 종료되면 데몬 쓰레드는 강제로 종료된다.
public class DaemonThread implements Runnable {

    @Override
    public void run() {
        while (true) {
            System.out.println("데몬쓰레드 실행 중");

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break; // 에러 발생 시 탈출을 위함
            }
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new DaemonThread());
        thread.setDaemon(true); // 쓰레드를 데몬쓰레드로 만들기 위한 설정
        thread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("메인 쓰레드 종료");
    }
}
post-custom-banner

0개의 댓글