From 5cb2123437ccb63fa5ed7e05ae79b7b3acf7a4e1 Mon Sep 17 00:00:00 2001 From: nannda3463 Date: Mon, 6 Nov 2023 10:24:03 +0900 Subject: [PATCH 1/3] =?UTF-8?q?FEAT=20(Thread)=20Thread=20=EC=97=B0?= =?UTF-8?q?=EC=8A=B5=EB=AC=B8=EC=A0=9C,=20=EA=B3=BC=EC=A0=9C=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nhnacademy/Jminsoo/exercise/Consumer.java | 56 ++++++++++++ .../com/nhnacademy/Jminsoo/exercise/Main.java | 25 ++++++ .../nhnacademy/Jminsoo/exercise/Producer.java | 40 +++++++++ .../nhnacademy/Jminsoo/exercise/Store.java | 90 +++++++++++++++++++ .../com/nhnacademy/Jminsoo/one/Consumer.java | 34 +++++++ .../java/com/nhnacademy/Jminsoo/one/Main.java | 21 +++++ .../java/com/nhnacademy/Jminsoo/one/Mart.java | 61 +++++++++++++ .../com/nhnacademy/Jminsoo/one/Producer.java | 34 +++++++ .../com/nhnacademy/Jminsoo/one/Store.java | 90 +++++++++++++++++++ .../Jminsoo/seamaphore/Consumer.java | 34 +++++++ .../nhnacademy/Jminsoo/seamaphore/Main.java | 21 +++++ .../nhnacademy/Jminsoo/seamaphore/Mart.java | 64 +++++++++++++ .../Jminsoo/seamaphore/Producer.java | 34 +++++++ .../nhnacademy/Jminsoo/seamaphore/Store.java | 88 ++++++++++++++++++ 14 files changed, 692 insertions(+) create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/one/Main.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/one/Mart.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/one/Producer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Main.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Producer.java create mode 100644 Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java new file mode 100644 index 0000000..767819a --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java @@ -0,0 +1,56 @@ +package com.nhnacademy.Jminsoo.exercise; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * 소비자는 매장에 입장 후 물건을 구매할 수 있다. + *

+ * 매장에는 입장 인원 제한이 있으므로, 인원 초과시 기다린다. + *

+ * 매장에 입장하면 물건을 구매하고, 퇴장한다. + *

+ * 1~10초 간격으로 구매한다. + */ +public class Consumer implements Runnable { + + Store store; + String name; + Thread thread; + int randNum; + + boolean isRun; + + + public Consumer(String name, Store store) { + this.name = name; + this.store = store; + this.thread = new Thread(this, name); + this.randNum = 0; + this.isRun = true; + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + this.store.enter(); + System.out.println(this.name + " 입장! 현재 손님 수 : " + this.store.getConsumerCount()); + while (isRun) { + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); + this.store.sell(); + System.out.println(this.name + " 구매! 현재 물건 개수 : " + this.store.getGoodsCount()); + isRun = false; + } + this.store.exit(); + System.out.println( + this.name + " 퇴장! 현재 손님 수 : " + this.store.getConsumerCount()); + + } catch (InterruptedException ignore) { + + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java new file mode 100644 index 0000000..15fd6a6 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java @@ -0,0 +1,25 @@ +package com.nhnacademy.Jminsoo.exercise; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; + +public class Main { + public static void main(String[] args) throws InterruptedException { + Store store = new Store(); + Producer producer = new Producer(store); + ExecutorService executorService = Executors.newFixedThreadPool(5); + producer.start(); + int index = 0; + while (true) { + if (store.getConsumerCount() < store.getMaxConsumerCount()) { + index++; + executorService.submit(new Consumer("손님" + index, store)); + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); + } + } + + } +} + diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java new file mode 100644 index 0000000..847a651 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java @@ -0,0 +1,40 @@ +package com.nhnacademy.Jminsoo.exercise; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * 생산자는 매장에 물건이 부족하지 않도록 채워둔다. + *

+ * 물건은 1~10초 간격으로 채운다. + *

+ * Thread내에서 난수 생성을 위해서는 ThreadLocalRandom.current().nextInt()를 사용하면 된다 + */ +public class Producer implements Runnable { + Thread thread; + Store store; + int randNum; + + public Producer(Store store) { + this.thread = new Thread(this); + this.store = store; + this.randNum = 0; + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + while (true) { + System.out.println("물건 공급 중!"); + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); + this.store.buy(); + System.out.println("물건 공급 완료! 현재 물건 개수 : " + this.store.getGoodsCount()); + } + } catch (InterruptedException ignore) { + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java new file mode 100644 index 0000000..96f11c1 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java @@ -0,0 +1,90 @@ +package com.nhnacademy.Jminsoo.exercise; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 매장은 물건을 납품 받아서 판매한다. + *

+ * 매장에는 최대 10개의 물건만 전시할 수 있다. : 최대 물건 개수 + *

+ * 매장은 최대 5명까지만 동시 입장 가능하다. : Consumer의 최대 접근 개수 + *

+ * 매장에서 물건 구매는 동시에 1명만 가능하다. : Syncronized. + *

+ * 매장에서 물건 판매 후 빈 공간에 생기면 생산자에게 알려 준다. : 생산자는 물건이 비면 깨어난다 + *

+ * 매장에서 물건 납품은 동시에 1명만 가능하다. : 납품 Syncronized + *

+ * 매장에서 물건이 들어오면 소비자에게 알려 준다. : 빈 물건이 들어오면 깬다. + */ +public class Store { + private final AtomicInteger maxGoodsCount; + private AtomicInteger goodsCount; + + private final AtomicInteger maxConsumerCount; + private AtomicInteger consumerCount; + + + public Store() { + this.maxGoodsCount = new AtomicInteger(10); + this.maxConsumerCount = new AtomicInteger(5); + this.goodsCount = new AtomicInteger(0); + this.consumerCount = new AtomicInteger(0); + + } + + public void enter() throws InterruptedException { + + if (this.consumerCount.get() >= this.maxConsumerCount.get()) { + wait(); + } + this.consumerCount.addAndGet(1); + } + + public void exit() { + this.consumerCount.addAndGet(-1); + } + + public synchronized void buy() throws InterruptedException { + while (true) { + if (this.goodsCount.get() >= this.maxGoodsCount.get()) { + System.out.println("창고가 꽉 찼다! 대기!"); + wait(); + } else { + this.goodsCount.addAndGet(1); + notifyAll(); + break; + } + } + + } + + public synchronized void sell() throws InterruptedException { + while (true) { + if (this.goodsCount.get() <= 0) { + wait(); + } else { + this.goodsCount.addAndGet(-1); + notifyAll(); + break; + } + } + } + + public synchronized int getGoodsCount() { + return this.goodsCount.intValue(); + } + + public synchronized int getConsumerCount() { + return this.consumerCount.intValue(); + } + + public synchronized int getMaxGoodsCount() { + return this.maxGoodsCount.intValue(); + } + + public synchronized int getMaxConsumerCount() { + return this.maxConsumerCount.intValue(); + } +} + diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java new file mode 100644 index 0000000..6e7a8fe --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java @@ -0,0 +1,34 @@ +package com.nhnacademy.Jminsoo.one; + +import java.util.concurrent.ThreadLocalRandom; + +public class Consumer implements Runnable { + + Mart mart; + String name; + Thread thread; + int randNum; + + + public Consumer(String name, Mart mart) { + this.name = name; + this.mart = mart; + this.thread = new Thread(this, name); + this.randNum = 0; + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + this.mart.enter(); + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1000); + } catch (InterruptedException ignore) { + } + System.out.println(this.name + " 마트 탈출!"); + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Main.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Main.java new file mode 100644 index 0000000..f3dd7ae --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Main.java @@ -0,0 +1,21 @@ +package com.nhnacademy.Jminsoo.one; + +import java.util.concurrent.ThreadLocalRandom; + + +public class Main { + public static void main(String[] args) throws InterruptedException { + Mart mart = new Mart(); + Producer producer = new Producer(mart); + producer.start(); + + + int index = 0; + while (true) { + index++; + new Consumer("손님" + index, mart).start(); + int randNum = ThreadLocalRandom.current().nextInt(1, 4); + Thread.sleep(randNum * 1_000L); + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Mart.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Mart.java new file mode 100644 index 0000000..ee50239 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Mart.java @@ -0,0 +1,61 @@ +package com.nhnacademy.Jminsoo.one; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; + +public class Mart { + + private List storeList; + private final AtomicInteger martSize; + private AtomicInteger randNum; + + + public Mart() { + this.martSize = new AtomicInteger(StoreType.values().length); + this.storeList = new ArrayList<>(); + this.randNum = new AtomicInteger(0); + addStore(); + } + + private void addStore() { + for (StoreType type : StoreType.values()) { + this.storeList.add(new Store(type.name())); + } + } + + public void supply() throws InterruptedException { + setRandNum(); + this.storeList.get(this.randNum.get()).buy(); + } + + + public void enter() throws InterruptedException { + setRandNum(); + Store tempStore = this.storeList.get(randNum.get()); + if (tempStore.getConsumerCount() < tempStore.getMaxConsumerCount()) { + tempStore.enter(); + tempStore.sell(); + tempStore.exit(); + } + } + + public synchronized void setRandNum() { + this.randNum.set(ThreadLocalRandom.current().nextInt(1, this.martSize.get())); + } + + private enum StoreType { + 축산매장, + 수산매장, + 빵집, + 피자집, + 삼성스토어, + 애플스토어, + 당X치킨, + 일반과자집; + + + } + +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Producer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Producer.java new file mode 100644 index 0000000..2f623c6 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Producer.java @@ -0,0 +1,34 @@ +package com.nhnacademy.Jminsoo.one; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; + +public class Producer implements Runnable { + private Thread thread; + private Mart mart; + + private AtomicInteger randNum; + + + public Producer(Mart mart) { + this.thread = new Thread(this); + this.mart = mart; + this.randNum = new AtomicInteger(); + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + while (true) { + this.randNum.set(ThreadLocalRandom.current().nextInt(1, 6)); + Thread.sleep(randNum.get() * 100); + this.mart.supply(); + } + } catch (InterruptedException ignore) { + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java new file mode 100644 index 0000000..5c5310b --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java @@ -0,0 +1,90 @@ +package com.nhnacademy.Jminsoo.one; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Store { + private final AtomicInteger maxGoodsCount; + private AtomicInteger goodsCount; + + private final AtomicInteger maxConsumerCount; + private AtomicInteger consumerCount; + + private String name; + + + public Store(String name) { + this.maxGoodsCount = new AtomicInteger(10); + this.maxConsumerCount = new AtomicInteger(5); + this.goodsCount = new AtomicInteger(0); + this.consumerCount = new AtomicInteger(0); + this.name = name; + } + + public void enter() { + while (true) { + try { + if (this.getConsumerCount() < this.getMaxConsumerCount()) { + this.consumerCount.addAndGet(1); + System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); + break; + } else { + wait(); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + } + + public void exit() { + System.out.println( + "[구매자] " + this.name + " 퇴장! 현재 손님 수 : " + this.getConsumerCount()); + this.consumerCount.addAndGet(-1); + } + + public synchronized void buy() { + System.out.println("[공급자] " + this.name + " 물건 공급 중!"); + if (this.getGoodsCount() >= this.getMaxGoodsCount()) { + System.out.println("[공급자] " + this.name + " 창고가 꽉 찼다! 대기!"); + } else { + this.goodsCount.addAndGet(1); + System.out.println("[공급자] " + this.name + " 물건 공급 완료! 현재 물건 개수 : " + this.getGoodsCount()); + notifyAll(); + } + } + + public synchronized void sell() throws InterruptedException { + + while (true) { + if (this.goodsCount.get() <= 0) { + System.out.println("[구매자] " + this.name + " 구매자 물건 없어서 대기!"); + wait(); + } else { + this.goodsCount.addAndGet(-1); + System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); + notifyAll(); + break; + } + } + } + + public synchronized int getGoodsCount() { + return this.goodsCount.intValue(); + } + + public synchronized int getConsumerCount() { + return this.consumerCount.intValue(); + } + + public synchronized int getMaxGoodsCount() { + return this.maxGoodsCount.intValue(); + } + + public synchronized int getMaxConsumerCount() { + return this.maxConsumerCount.intValue(); + } + + +} + diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java new file mode 100644 index 0000000..c18a707 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java @@ -0,0 +1,34 @@ +package com.nhnacademy.Jminsoo.seamaphore; + +import java.util.concurrent.ThreadLocalRandom; + +public class Consumer implements Runnable { + + Mart mart; + String name; + Thread thread; + int randNum; + + + public Consumer(String name, Mart mart) { + this.name = name; + this.mart = mart; + this.thread = new Thread(this, name); + this.randNum = 0; + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + this.mart.enter(); + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); + } catch (InterruptedException ignore) { + } + System.out.println(this.name + " 마트 탈출!"); + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Main.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Main.java new file mode 100644 index 0000000..b57c6e8 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Main.java @@ -0,0 +1,21 @@ +package com.nhnacademy.Jminsoo.seamaphore; + +import java.util.concurrent.ThreadLocalRandom; + + +public class Main { + public static void main(String[] args) throws InterruptedException { + Mart mart = new Mart(); + Producer producer = new Producer(mart); + producer.start(); + + + int index = 0; + while (true) { + index++; + new Consumer("손님" + index, mart).start(); + int randNum = ThreadLocalRandom.current().nextInt(1, 6); + Thread.sleep(randNum * 1_000L); + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java new file mode 100644 index 0000000..014a967 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java @@ -0,0 +1,64 @@ +package com.nhnacademy.Jminsoo.seamaphore; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Semaphore; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; + +public class Mart { + + private List storeList; + private final AtomicInteger martSize; + private AtomicInteger randNum; + + private final Semaphore semaphore; + + + public Mart() { + this.martSize = new AtomicInteger(StoreType.values().length); + this.storeList = new ArrayList<>(); + this.randNum = new AtomicInteger(0); + addStore(); + semaphore = new Semaphore(10, true); + } + + private void addStore() { + for (StoreType type : StoreType.values()) { + this.storeList.add(new Store(type.name())); + } + } + + public void supply() throws InterruptedException { + this.storeList.get(ThreadLocalRandom.current().nextInt(1, this.martSize.get())).buy(); + } + + + public void enter() throws InterruptedException { + setRandNum(); + Store tempStore = this.storeList.get(randNum.get()); + if (tempStore.getConsumerCount() < tempStore.getMaxConsumerCount()) { + tempStore.enter(); + tempStore.sell(); + tempStore.exit(); + } + } + + public void setRandNum() { + this.randNum.set(ThreadLocalRandom.current().nextInt(1, this.martSize.get())); + } + + private enum StoreType { + 축산매장, + 수산매장, + 빵집, +// 피자집, +// 삼성스토어, +// 애플스토어, +// 당X치킨, +// 일반과자집; + + + } + +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Producer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Producer.java new file mode 100644 index 0000000..fc41a89 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Producer.java @@ -0,0 +1,34 @@ +package com.nhnacademy.Jminsoo.seamaphore; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; + +public class Producer implements Runnable { + private Thread thread; + private Mart mart; + + private AtomicInteger randNum; + + + public Producer(Mart mart) { + this.thread = new Thread(this); + this.mart = mart; + this.randNum = new AtomicInteger(); + } + + public void start() { + this.thread.start(); + } + + @Override + public void run() { + try { + while (true) { + this.randNum.set(ThreadLocalRandom.current().nextInt(1, 6)); + Thread.sleep(randNum.get() * 1_000L); + this.mart.supply(); + } + } catch (InterruptedException ignore) { + } + } +} diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java new file mode 100644 index 0000000..f0c6c64 --- /dev/null +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java @@ -0,0 +1,88 @@ +package com.nhnacademy.Jminsoo.seamaphore; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; + +public class Store { + private final AtomicInteger maxGoodsCount; + private AtomicInteger goodsCount; + + private final AtomicInteger maxConsumerCount; + private AtomicInteger consumerCount; + + private String name; + + private final Semaphore enterSemaphore; + private final Semaphore sellSemaphore; + + + public Store(String name) { + this.maxGoodsCount = new AtomicInteger(10); + this.maxConsumerCount = new AtomicInteger(5); + this.goodsCount = new AtomicInteger(0); + this.consumerCount = new AtomicInteger(0); + this.name = name; + this.enterSemaphore = new Semaphore(5, true); + this.sellSemaphore = new Semaphore(10, true); + } + + public void enter() throws InterruptedException { + this.enterSemaphore.acquire(); + this.consumerCount.addAndGet(1); + System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); + this.enterSemaphore.release(); + + } + + public void exit() { + System.out.println( + "[구매자] " + this.name + " 퇴장! 현재 손님 수 : " + this.getConsumerCount()); + this.consumerCount.addAndGet(-1); + } + + public synchronized void buy() throws InterruptedException { + System.out.println("[공급자] " + this.name + " 물건 공급 중!"); + if (this.getGoodsCount() >= this.getMaxGoodsCount()) { + System.out.println("[공급자] " + this.name + " 창고가 꽉 찼다! 대기!"); + } else { + this.goodsCount.addAndGet(1); + System.out.println("[공급자] " + this.name + " 물건 공급 완료! 현재 물건 개수 : " + this.getGoodsCount()); + notifyAll(); + } + } + + public synchronized void sell() throws InterruptedException { + this.sellSemaphore.acquire(); + + while (true) { + if (this.getGoodsCount() > 0) { + this.sellSemaphore.release(); + this.goodsCount.addAndGet(-1); + System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); + notifyAll(); + break; + } else { + wait(); + } + } + } + + public synchronized int getGoodsCount() { + return this.goodsCount.intValue(); + } + + public synchronized int getConsumerCount() { + return this.consumerCount.intValue(); + } + + public synchronized int getMaxGoodsCount() { + return this.maxGoodsCount.intValue(); + } + + public synchronized int getMaxConsumerCount() { + return this.maxConsumerCount.intValue(); + } + + +} + From 4f9b867baad12b68aef7b12ab9f2f481593eb277 Mon Sep 17 00:00:00 2001 From: nannda3463 Date: Tue, 7 Nov 2023 13:15:57 +0900 Subject: [PATCH 2/3] =?UTF-8?q?REFACTOR=20(Thread)=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20*=20mart=20=EA=B5=AC=EC=A1=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20*=20store=20=EC=84=B8=EB=A7=88=ED=8F=AC=EC=96=B4=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nhnacademy/Jminsoo/exercise/Consumer.java | 22 +++------- .../com/nhnacademy/Jminsoo/exercise/Main.java | 12 ++--- .../nhnacademy/Jminsoo/exercise/Producer.java | 13 +++--- .../nhnacademy/Jminsoo/exercise/Store.java | 44 +++++++------------ .../com/nhnacademy/Jminsoo/one/Consumer.java | 9 ++-- .../com/nhnacademy/Jminsoo/one/Store.java | 38 ++++++---------- .../Jminsoo/seamaphore/Consumer.java | 8 ++-- .../nhnacademy/Jminsoo/seamaphore/Mart.java | 36 ++++++--------- .../nhnacademy/Jminsoo/seamaphore/Store.java | 25 +++++------ 9 files changed, 81 insertions(+), 126 deletions(-) diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java index 767819a..611d840 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java @@ -13,20 +13,15 @@ */ public class Consumer implements Runnable { - Store store; - String name; - Thread thread; - int randNum; - - boolean isRun; + private Store store; + private String name; + private Thread thread; public Consumer(String name, Store store) { this.name = name; this.store = store; this.thread = new Thread(this, name); - this.randNum = 0; - this.isRun = true; } public void start() { @@ -38,13 +33,10 @@ public void run() { try { this.store.enter(); System.out.println(this.name + " 입장! 현재 손님 수 : " + this.store.getConsumerCount()); - while (isRun) { - int randNum = ThreadLocalRandom.current().nextInt(1, 11); - Thread.sleep(randNum * 1_000L); - this.store.sell(); - System.out.println(this.name + " 구매! 현재 물건 개수 : " + this.store.getGoodsCount()); - isRun = false; - } + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); + this.store.sell(); + System.out.println(this.name + " 구매! 현재 물건 개수 : " + this.store.getGoodsCount()); this.store.exit(); System.out.println( this.name + " 퇴장! 현재 손님 수 : " + this.store.getConsumerCount()); diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java index 15fd6a6..438fb2f 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java @@ -12,12 +12,12 @@ public static void main(String[] args) throws InterruptedException { producer.start(); int index = 0; while (true) { - if (store.getConsumerCount() < store.getMaxConsumerCount()) { - index++; - executorService.submit(new Consumer("손님" + index, store)); - int randNum = ThreadLocalRandom.current().nextInt(1, 11); - Thread.sleep(randNum * 1_000L); - } +// if (store.getConsumerCount() < store.getMAX_CONSUMER_COUNTS()) { + index++; + executorService.submit(new Consumer("손님" + index, store)); + int randNum = ThreadLocalRandom.current().nextInt(1, 11); + Thread.sleep(randNum * 1_000L); +// } } } diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java index 847a651..a7dfd36 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java @@ -10,14 +10,12 @@ * Thread내에서 난수 생성을 위해서는 ThreadLocalRandom.current().nextInt()를 사용하면 된다 */ public class Producer implements Runnable { - Thread thread; - Store store; - int randNum; + private Thread thread; + private Store store; public Producer(Store store) { this.thread = new Thread(this); this.store = store; - this.randNum = 0; } public void start() { @@ -29,12 +27,15 @@ public void run() { try { while (true) { System.out.println("물건 공급 중!"); - int randNum = ThreadLocalRandom.current().nextInt(1, 11); - Thread.sleep(randNum * 1_000L); + Thread.sleep(getRandNum() * 1_000L); this.store.buy(); System.out.println("물건 공급 완료! 현재 물건 개수 : " + this.store.getGoodsCount()); } } catch (InterruptedException ignore) { } } + + private int getRandNum() { + return ThreadLocalRandom.current().nextInt(1, 11); + } } diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java index 96f11c1..cec0ccd 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java @@ -18,16 +18,14 @@ * 매장에서 물건이 들어오면 소비자에게 알려 준다. : 빈 물건이 들어오면 깬다. */ public class Store { - private final AtomicInteger maxGoodsCount; + private final AtomicInteger MAX_GOODS_COUNTS = new AtomicInteger(10); + private final AtomicInteger MAX_CONSUMER_COUNTS = new AtomicInteger(5); private AtomicInteger goodsCount; - private final AtomicInteger maxConsumerCount; private AtomicInteger consumerCount; public Store() { - this.maxGoodsCount = new AtomicInteger(10); - this.maxConsumerCount = new AtomicInteger(5); this.goodsCount = new AtomicInteger(0); this.consumerCount = new AtomicInteger(0); @@ -35,7 +33,7 @@ public Store() { public void enter() throws InterruptedException { - if (this.consumerCount.get() >= this.maxConsumerCount.get()) { + if (this.consumerCount.get() >= this.MAX_CONSUMER_COUNTS.get()) { wait(); } this.consumerCount.addAndGet(1); @@ -46,29 +44,21 @@ public void exit() { } public synchronized void buy() throws InterruptedException { - while (true) { - if (this.goodsCount.get() >= this.maxGoodsCount.get()) { - System.out.println("창고가 꽉 찼다! 대기!"); - wait(); - } else { - this.goodsCount.addAndGet(1); - notifyAll(); - break; - } - } + while (this.goodsCount.get() >= this.MAX_GOODS_COUNTS.get()) { + System.out.println("창고가 꽉 찼다! 대기!"); + wait(); + } + this.goodsCount.addAndGet(1); + notifyAll(); } public synchronized void sell() throws InterruptedException { - while (true) { - if (this.goodsCount.get() <= 0) { - wait(); - } else { - this.goodsCount.addAndGet(-1); - notifyAll(); - break; - } + while (this.goodsCount.get() <= 0) { + wait(); } + this.goodsCount.addAndGet(-1); + notifyAll(); } public synchronized int getGoodsCount() { @@ -79,12 +69,12 @@ public synchronized int getConsumerCount() { return this.consumerCount.intValue(); } - public synchronized int getMaxGoodsCount() { - return this.maxGoodsCount.intValue(); + public synchronized int getMAX_GOODS_COUNTS() { + return this.MAX_GOODS_COUNTS.intValue(); } - public synchronized int getMaxConsumerCount() { - return this.maxConsumerCount.intValue(); + public synchronized int getMAX_CONSUMER_COUNTS() { + return this.MAX_CONSUMER_COUNTS.intValue(); } } diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java index 6e7a8fe..972f676 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java @@ -4,17 +4,14 @@ public class Consumer implements Runnable { - Mart mart; - String name; - Thread thread; - int randNum; - + private Mart mart; + private String name; + private Thread thread; public Consumer(String name, Mart mart) { this.name = name; this.mart = mart; this.thread = new Thread(this, name); - this.randNum = 0; } public void start() { diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java index 5c5310b..87abb78 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/one/Store.java @@ -3,37 +3,31 @@ import java.util.concurrent.atomic.AtomicInteger; public class Store { - private final AtomicInteger maxGoodsCount; + private final AtomicInteger MAX_GOODS_COUNTS = new AtomicInteger(10); + private final AtomicInteger MAX_CONSUMER_COUNTS = new AtomicInteger(5); private AtomicInteger goodsCount; - private final AtomicInteger maxConsumerCount; private AtomicInteger consumerCount; private String name; public Store(String name) { - this.maxGoodsCount = new AtomicInteger(10); - this.maxConsumerCount = new AtomicInteger(5); this.goodsCount = new AtomicInteger(0); this.consumerCount = new AtomicInteger(0); this.name = name; } public void enter() { - while (true) { + while (this.getConsumerCount() >= this.getMaxConsumerCount()) { try { - if (this.getConsumerCount() < this.getMaxConsumerCount()) { - this.consumerCount.addAndGet(1); - System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); - break; - } else { - wait(); - } + wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } + this.consumerCount.addAndGet(1); + System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); } @@ -56,17 +50,13 @@ public synchronized void buy() { public synchronized void sell() throws InterruptedException { - while (true) { - if (this.goodsCount.get() <= 0) { - System.out.println("[구매자] " + this.name + " 구매자 물건 없어서 대기!"); - wait(); - } else { - this.goodsCount.addAndGet(-1); - System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); - notifyAll(); - break; - } + while (this.goodsCount.get() <= 0) { + System.out.println("[구매자] " + this.name + " 구매자 물건 없어서 대기!"); + wait(); } + this.goodsCount.addAndGet(-1); + System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); + notifyAll(); } public synchronized int getGoodsCount() { @@ -78,11 +68,11 @@ public synchronized int getConsumerCount() { } public synchronized int getMaxGoodsCount() { - return this.maxGoodsCount.intValue(); + return this.MAX_GOODS_COUNTS.intValue(); } public synchronized int getMaxConsumerCount() { - return this.maxConsumerCount.intValue(); + return this.MAX_CONSUMER_COUNTS.intValue(); } diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java index c18a707..837bc15 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Consumer.java @@ -4,17 +4,15 @@ public class Consumer implements Runnable { - Mart mart; - String name; - Thread thread; - int randNum; + private Mart mart; + private String name; + private Thread thread; public Consumer(String name, Mart mart) { this.name = name; this.mart = mart; this.thread = new Thread(this, name); - this.randNum = 0; } public void start() { diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java index 014a967..5a8b27c 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Mart.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; @@ -10,17 +9,12 @@ public class Mart { private List storeList; private final AtomicInteger martSize; - private AtomicInteger randNum; - - private final Semaphore semaphore; public Mart() { this.martSize = new AtomicInteger(StoreType.values().length); this.storeList = new ArrayList<>(); - this.randNum = new AtomicInteger(0); addStore(); - semaphore = new Semaphore(10, true); } private void addStore() { @@ -29,36 +23,34 @@ private void addStore() { } } - public void supply() throws InterruptedException { - this.storeList.get(ThreadLocalRandom.current().nextInt(1, this.martSize.get())).buy(); + public void supply() { + this.storeList.get(this.getRandNum(this.martSize.get())).buy(); } public void enter() throws InterruptedException { - setRandNum(); - Store tempStore = this.storeList.get(randNum.get()); - if (tempStore.getConsumerCount() < tempStore.getMaxConsumerCount()) { - tempStore.enter(); - tempStore.sell(); - tempStore.exit(); - } + Store tempStore = this.storeList.get(this.getRandNum(this.martSize.get())); + tempStore.enter(); + tempStore.sell(); + tempStore.exit(); } - public void setRandNum() { - this.randNum.set(ThreadLocalRandom.current().nextInt(1, this.martSize.get())); + private int getRandNum(int bound) { + return ThreadLocalRandom.current().nextInt(1, bound); } private enum StoreType { 축산매장, 수산매장, 빵집, -// 피자집, -// 삼성스토어, -// 애플스토어, -// 당X치킨, -// 일반과자집; + 피자집, + 삼성스토어, + 애플스토어, + 당X치킨, + 일반과자집; } + } diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java index f0c6c64..3c9c8b0 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java @@ -4,33 +4,28 @@ import java.util.concurrent.atomic.AtomicInteger; public class Store { - private final AtomicInteger maxGoodsCount; + private final AtomicInteger MAX_GOODS_COUNTS = new AtomicInteger(10); + private final AtomicInteger MAX_CONSUMER_COUNTS = new AtomicInteger(5); private AtomicInteger goodsCount; - private final AtomicInteger maxConsumerCount; private AtomicInteger consumerCount; private String name; - private final Semaphore enterSemaphore; - private final Semaphore sellSemaphore; + private final Semaphore consumerSemaphore; public Store(String name) { - this.maxGoodsCount = new AtomicInteger(10); - this.maxConsumerCount = new AtomicInteger(5); this.goodsCount = new AtomicInteger(0); this.consumerCount = new AtomicInteger(0); this.name = name; - this.enterSemaphore = new Semaphore(5, true); - this.sellSemaphore = new Semaphore(10, true); + this.consumerSemaphore = new Semaphore(5, true); } public void enter() throws InterruptedException { - this.enterSemaphore.acquire(); + this.consumerSemaphore.acquire(); this.consumerCount.addAndGet(1); System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); - this.enterSemaphore.release(); } @@ -38,9 +33,11 @@ public void exit() { System.out.println( "[구매자] " + this.name + " 퇴장! 현재 손님 수 : " + this.getConsumerCount()); this.consumerCount.addAndGet(-1); + this.consumerSemaphore.release(); } - public synchronized void buy() throws InterruptedException { + + public synchronized void buy() { System.out.println("[공급자] " + this.name + " 물건 공급 중!"); if (this.getGoodsCount() >= this.getMaxGoodsCount()) { System.out.println("[공급자] " + this.name + " 창고가 꽉 찼다! 대기!"); @@ -52,11 +49,9 @@ public synchronized void buy() throws InterruptedException { } public synchronized void sell() throws InterruptedException { - this.sellSemaphore.acquire(); while (true) { if (this.getGoodsCount() > 0) { - this.sellSemaphore.release(); this.goodsCount.addAndGet(-1); System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); notifyAll(); @@ -76,11 +71,11 @@ public synchronized int getConsumerCount() { } public synchronized int getMaxGoodsCount() { - return this.maxGoodsCount.intValue(); + return this.MAX_GOODS_COUNTS.intValue(); } public synchronized int getMaxConsumerCount() { - return this.maxConsumerCount.intValue(); + return this.MAX_CONSUMER_COUNTS.intValue(); } From 2865f2b3a8c2e10ddbc03197226275b53c5584d4 Mon Sep 17 00:00:00 2001 From: nannda3463 Date: Tue, 7 Nov 2023 13:26:32 +0900 Subject: [PATCH 3/3] =?UTF-8?q?REFACTOR=20(Thread)=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20*=20store=20=ED=95=84=EC=9A=94=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EB=B3=80=EC=88=98,=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nhnacademy/Jminsoo/seamaphore/Store.java | 43 +++++-------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java index 3c9c8b0..cc21f0f 100644 --- a/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java +++ b/Thread/src/main/java/com/nhnacademy/Jminsoo/seamaphore/Store.java @@ -5,7 +5,6 @@ public class Store { private final AtomicInteger MAX_GOODS_COUNTS = new AtomicInteger(10); - private final AtomicInteger MAX_CONSUMER_COUNTS = new AtomicInteger(5); private AtomicInteger goodsCount; private AtomicInteger consumerCount; @@ -23,15 +22,16 @@ public Store(String name) { } public void enter() throws InterruptedException { + System.out.println( + "[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.consumerCount.get()); this.consumerSemaphore.acquire(); this.consumerCount.addAndGet(1); - System.out.println("[구매자] " + this.name + " 입장! 현재 손님 수 : " + this.getConsumerCount()); } public void exit() { System.out.println( - "[구매자] " + this.name + " 퇴장! 현재 손님 수 : " + this.getConsumerCount()); + "[구매자] " + this.name + " 퇴장! 현재 손님 수 : " + this.consumerCount.get()); this.consumerCount.addAndGet(-1); this.consumerSemaphore.release(); } @@ -39,45 +39,22 @@ public void exit() { public synchronized void buy() { System.out.println("[공급자] " + this.name + " 물건 공급 중!"); - if (this.getGoodsCount() >= this.getMaxGoodsCount()) { + if (this.goodsCount.get() >= this.MAX_GOODS_COUNTS.get()) { System.out.println("[공급자] " + this.name + " 창고가 꽉 찼다! 대기!"); } else { this.goodsCount.addAndGet(1); - System.out.println("[공급자] " + this.name + " 물건 공급 완료! 현재 물건 개수 : " + this.getGoodsCount()); + System.out.println("[공급자] " + this.name + " 물건 공급 완료! 현재 물건 개수 : " + this.goodsCount.get()); notifyAll(); } } public synchronized void sell() throws InterruptedException { - - while (true) { - if (this.getGoodsCount() > 0) { - this.goodsCount.addAndGet(-1); - System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.getGoodsCount()); - notifyAll(); - break; - } else { - wait(); - } + while (this.goodsCount.get() <= 0) { + wait(); } + this.goodsCount.addAndGet(-1); + System.out.println("[구매자] " + this.name + " 물건 판매! 현재 물건 개수 : " + this.goodsCount.get()); + notifyAll(); } - - public synchronized int getGoodsCount() { - return this.goodsCount.intValue(); - } - - public synchronized int getConsumerCount() { - return this.consumerCount.intValue(); - } - - public synchronized int getMaxGoodsCount() { - return this.MAX_GOODS_COUNTS.intValue(); - } - - public synchronized int getMaxConsumerCount() { - return this.MAX_CONSUMER_COUNTS.intValue(); - } - - }