인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

lgh8079님의 프로필 이미지
lgh8079

작성한 질문수

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

생산자 소비자 문제 - 예제1 분석 - 생산자 우선

56강에 대한 질문입니다(BoundedMain).

작성

·

88

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]
package thread.bounded; import static util.MyLogger.log; public class ProducerTask implements Runnable { private BoundedQueue queue; private String request; public ProducerTask(BoundedQueue queue, String request) { this.queue = queue; this.request = request; } @Override public void run() { log("[생산 시도] " + request + " -> " + queue); log("[생산 완료] " + request + " -> " + queue); } }

package thread.bounded; import static util.MyLogger.log; public class ConsumerTask implements Runnable { private BoundedQueue queue; public ConsumerTask(BoundedQueue queue) { this.queue = queue; } @Override public void run() { log("[소비 시도] ? <- " + queue); String data = queue.take(); log("[소비 완료] " + data + " <- " + queue); } }

package thread.bounded; public interface BoundedQueue { void put(String data); String take(); }

package thread.bounded; import java.util.ArrayList; import java.util.List; import static util.MyLogger.log; import static util.ThreadUtils.sleep; public class BoundedMain { public static void main(String[] args) { // 1. BoundedQueue 선택 BoundedQueue queue = new BoundedQueueV1(2); // 2. 생산자, 소비자 실행 순서 선택, 반드시 하나만 선택! producerFirst(queue); // 생산자 먼저 실행 //consumerFirst(queue); // 소비자 먼저 실행 } private static void producerFirst(BoundedQueue queue) { log("== [생산자 먼저 실행] 시작, " + queue.getClass().getSimpleName() + " =="); List<Thread> threads = new ArrayList<>(); startProducer(queue, threads); printAllState(queue, threads); startConsumer(queue, threads); printAllState(queue, threads); log("== [생산자 먼저 실행] 종료, " + queue.getClass().getSimpleName() + " =="); } private static void consumerFirst(BoundedQueue queue) { log("== [소비자 먼저 실행] 시작, " + queue.getClass().getSimpleName() + " =="); List<Thread> threads = new ArrayList<>(); startConsumer(queue, threads); printAllState(queue, threads); startProducer(queue, threads); printAllState(queue, threads); log("== [소비자 먼저 실행] 종료, " + queue.getClass().getSimpleName() + " =="); } private static void startProducer(BoundedQueue queue, List<Thread> threads) { System.out.println(); log("생산자 시작"); for (int i = 1; i <= 3; i++) { Thread producer = new Thread(new ProducerTask(queue, "data" + i), "producer" + i); threads.add(producer); producer.start(); sleep(100); } } private static void startConsumer(BoundedQueue queue, List<Thread> threads) { System.out.println(); log("소비자 시작"); for (int i = 1; i <= 3; i++) { Thread consumer = new Thread(new ConsumerTask(queue), "consumer" + i); threads.add(consumer); consumer.start(); sleep(100); } } private static void printAllState(BoundedQueue queue, List<Thread> threads) { System.out.println(); log("현재 상태 출력, 큐 데이터: " + queue); for (Thread thread : threads) { log(thread.getName() + ": " + thread.getState()); } } }

package thread.bounded; import java.util.ArrayDeque; import java.util.Queue; import static util.MyLogger.log; public class BoundedQueueV1 implements BoundedQueue { private final Queue<String> queue = new ArrayDeque<>(); private final int max; public BoundedQueueV1(int max) { this.max = max; } @Override public synchronized void put(String data) { if (queue.size() == max) { log("[put] 큐가 가득 참, 버림: " + data); return; } queue.offer(data); } @Override public synchronized String take() { if (queue.isEmpty()) { return null; } return queue.poll(); } @Override public String toString() { return queue.toString(); } }

C:\Users\lgh80\.jdks\temurin-21.0.4\bin\java.exe --enable-preview "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.1.4\lib\idea_rt.jar=52674:C:\Program Files\JetBrains\IntelliJ IDEA 2024.1.4\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\java-adv1\out\production\java-adv1 thread.bounded.BoundedMain

09:38:16.411 [ main] == [생산자 먼저 실행] 시작, BoundedQueueV1 ==

09:38:16.413 [ main] 생산자 시작

09:38:16.424 [producer1] [생산 시도] data1 -> []

09:38:16.425 [producer1] [생산 완료] data1 -> []

09:38:16.531 [producer2] [생산 시도] data2 -> []

09:38:16.532 [producer2] [생산 완료] data2 -> []

09:38:16.642 [producer3] [생산 시도] data3 -> []

09:38:16.642 [producer3] [생산 완료] data3 -> []

09:38:16.752 [ main] 현재 상태 출력, 큐 데이터: []

09:38:16.754 [ main] producer1: TERMINATED

09:38:16.754 [ main] producer2: TERMINATED

09:38:16.754 [ main] producer3: TERMINATED

09:38:16.755 [ main] 소비자 시작

09:38:16.757 [consumer1] [소비 시도] ? <- []

09:38:16.757 [consumer1] [소비 완료] null <- []

09:38:16.864 [consumer2] [소비 시도] ? <- []

09:38:16.865 [consumer2] [소비 완료] null <- []

09:38:16.974 [consumer3] [소비 시도] ? <- []

09:38:16.975 [consumer3] [소비 완료] null <- []

09:38:17.085 [ main] 현재 상태 출력, 큐 데이터: []

09:38:17.085 [ main] producer1: TERMINATED

09:38:17.086 [ main] producer2: TERMINATED

09:38:17.086 [ main] producer3: TERMINATED

09:38:17.086 [ main] consumer1: TERMINATED

09:38:17.087 [ main] consumer2: TERMINATED

09:38:17.087 [ main] consumer3: TERMINATED

09:38:17.087 [ main] == [생산자 먼저 실행] 종료, BoundedQueueV1 ==

Process finished with exit code 0



이런 식으로 출력이 뜨는데 강의 내용에 나와있는 로그 창이랑 많이 달라서 강의 코드랑도 비교해봤는데 어디에서 문제가 있는 건지 잘 모르겠습니다.

답변 2

0

ProducerTask의 run method 작성이 제대로 이루어지지 않은 것으로 보이네요!

run method 내부의 '생산시도 log'와 '생산완료 log' 사이에 BoundedQueue 버퍼에 데이터를 추가하는 put method를 추가하면 정상적으로 작동할 것 같네요!

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. BoundedQueue님

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

실제 동작하는 전체 프로젝트를 ZIP파일로 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

 

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명 (오류 화면, 오류 로그 포함)

링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

lgh8079님의 프로필 이미지
lgh8079

작성한 질문수

질문하기