Inflearn brand logo image

인프런 커뮤니티 질문&답변

dev.rudevico님의 프로필 이미지
dev.rudevico

작성한 질문수

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

프린터 예제4 - yield 도입

[코드 공유] yield() 유무에 따른 체크 로직 수행 횟수를 확인할 수 있는 코드 공유합니다.

해결된 질문

작성

·

93

·

수정됨

0

[비교 결론]

(맥북 프로 2018형 기준)

  • yield() 사용 X: 체크 로직 319_216_379회 수행

  • yield() 사용 O: 체크 로직 000_730_447회 수행

[코드 사용법]

  • 체크로직 while loop에 있는 Thread.yield();를 주석처리 on/off 하면서 체크하시면 됩니다.

  • 프로그램 수행 -> a, b, c, d, e, q를 순서대로 입력

  • 위 두 동작을 주석처리 on/off한 후에 실행하는 두 경우 모두에서 비슷한 속도로 해 주시면 비교가 더 명확합니다.

 

[코드 설명]

MyPrinterV4 코드를 기준으로 하여 다음과 같이 체크 로직의 수행 횟수를 카운트할 수 있도록 개선했습니다. 러프하게 작성한 코드라서 세부적인 부분은 무시바랍니다.

// 체크 로직의 수행 횟수를 기록하는 변수
private static int count = 0;
while (!Thread.interrupted()) {
    if (jobQueue.isEmpty()) {
        count++; // 체크 로직 수행시 1회 추가 기록
        Thread.yield(); // 여기를 On/Off하며 체크
        continue;
    }
}
// 메인 함수의 마지막 부분에 추가한 코드
// q를 입력하여 프로그램을 종료했을 때까지 수행된 체크 로직의 횟수를 출력
System.out.println(count);

[전체 코드]

package thread.control.printer;

import java.util.Queue;
import java.util.Scanner;
import java.util.concurrent.ConcurrentLinkedQueue;

import static util.MyLogger.log;

public class MyPrinterV4 {

    // 추가된 코드
    private static int count = 0;

    public static void main(String[] args) {
        Printer printer = new Printer();
        Thread printerThread = new Thread(printer, "printer");
        printerThread.start();

        Scanner userInput = new Scanner(System.in);
        while (true) {
            log("프린터할 문서를 입력하세요. 종료 (q): ");
            String input = userInput.nextLine();
            if (input.equals("q")) {
                printerThread.interrupt(); 
                break;
            }

            printer.addJob(input);
        }
        // 추가된 코드
        System.out.println(count);

    }

    static class Printer implements Runnable {

        Queue<String> jobQueue = new ConcurrentLinkedQueue<>();

        @Override
        public void run() {

            while (!Thread.interrupted()) {
                if (jobQueue.isEmpty()) {
                    // 코드 추가된 부분(시작)
                    count++;
                    Thread.yield(); // 주석 on/off 하며 비교
                    // 코드 추가된 부분(종료)
                    continue;
                }

                try {
                    String job = jobQueue.poll();
                    log("출력 시작: " + job + ", 대기 문서: " + jobQueue);
                    Thread.sleep(3000);
                    log("출력 완료: " + job);
                } catch (InterruptedException e) {
                    log("인터럽트 발생. message=" + e.getMessage());
                    break;
                }
            }
            log("프린터 종료");
        }

        public void addJob(String input) {
            jobQueue.offer(input);
        }
    }
}

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

dev.rudevico님께서 공유해주신 yield() 여부에 따른 체크 로직의 수행 횟수를 확인할 수 있는 코드에 대한 실험은 자바의 Thread.yield() 메서드가 실제로 시스템 스케줄링에 얼마나 영향을 미치는지 보여주는 좋은 예시입니다.

Thread.yield()는 현재 스레드가 실행 중인 작업에서 물러나 다른 가능한 스레드에게 CPU를 양보하는 역할을 합니다. 일반적으로 이 메서드는 스레드 우선순위가 동일한 다른 스레드에게 자원을 제공하려고 할 때 사용됩니다. 따라서 yield()를 사용할 경우, 다른 스레드가 더 빠르게 교체되어 실행될 수 있어 체크 로직의 수행 횟수가 줄어들 수 있습니다.

하지만, yield()의 실제 동작은 JVM 구현 및 운영 체제에 밀접하게 의존하므로, 반드시 실행 횟수나 실행 시점에 큰 차이를 주지 않을 수도 있습니다. 이는 주로 프로세스 스케줄러의 구현 및 시스템의 부하 상태에 따라서 달라질 수 있습니다.

관련하여 비슷한 내용이 논의된 인터럽트 - Thread의 사용 게시물을 참고하시면 추가적인 이해에 도움이 될 수 있습니다.

또한, Thread.interrupt()를 사용하는 방법과 관련된 질문과 답변은 인터럽트에 대해 질문 있습니다 게시물에서 확인하실 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

dev.rudevico님의 프로필 이미지
dev.rudevico

작성한 질문수

질문하기