-
Notifications
You must be signed in to change notification settings - Fork 0
Thread Jminsoo #42
base: main
Are you sure you want to change the base?
Thread Jminsoo #42
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package com.nhnacademy.Jminsoo.exercise; | ||
|
|
||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| /** | ||
| * 소비자는 매장에 입장 후 물건을 구매할 수 있다. | ||
| * <p> | ||
| * 매장에는 입장 인원 제한이 있으므로, 인원 초과시 기다린다. | ||
| * <p> | ||
| * 매장에 입장하면 물건을 구매하고, 퇴장한다. | ||
| * <p> | ||
| * 1~10초 간격으로 구매한다. | ||
| */ | ||
| public class Consumer implements Runnable { | ||
|
|
||
| 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); | ||
| } | ||
|
|
||
| public void start() { | ||
| this.thread.start(); | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| try { | ||
| this.store.enter(); | ||
| System.out.println(this.name + " 입장! 현재 손님 수 : " + this.store.getConsumerCount()); | ||
| 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()); | ||
|
|
||
| } catch (InterruptedException ignore) { | ||
|
|
||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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.getMAX_CONSUMER_COUNTS()) { | ||
| index++; | ||
| executorService.submit(new Consumer("손님" + index, store)); | ||
| int randNum = ThreadLocalRandom.current().nextInt(1, 11); | ||
| Thread.sleep(randNum * 1_000L); | ||
| // } | ||
| } | ||
|
|
||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package com.nhnacademy.Jminsoo.exercise; | ||
|
|
||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| /** | ||
| * 생산자는 매장에 물건이 부족하지 않도록 채워둔다. | ||
| * <p> | ||
| * 물건은 1~10초 간격으로 채운다. | ||
| * <p> | ||
| * Thread내에서 난수 생성을 위해서는 ThreadLocalRandom.current().nextInt()를 사용하면 된다 | ||
| */ | ||
| public class Producer implements Runnable { | ||
| private Thread thread; | ||
| private Store store; | ||
|
|
||
| public Producer(Store store) { | ||
| this.thread = new Thread(this); | ||
| this.store = store; | ||
| } | ||
|
|
||
| public void start() { | ||
| this.thread.start(); | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| try { | ||
| while (true) { | ||
| System.out.println("물건 공급 중!"); | ||
| 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); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| package com.nhnacademy.Jminsoo.exercise; | ||
|
|
||
| import java.util.concurrent.atomic.AtomicInteger; | ||
|
|
||
| /** | ||
| * 매장은 물건을 납품 받아서 판매한다. | ||
| * <p> | ||
| * 매장에는 최대 10개의 물건만 전시할 수 있다. : 최대 물건 개수 | ||
| * <p> | ||
| * 매장은 최대 5명까지만 동시 입장 가능하다. : Consumer의 최대 접근 개수 | ||
| * <p> | ||
| * 매장에서 물건 구매는 동시에 1명만 가능하다. : Syncronized. | ||
| * <p> | ||
| * 매장에서 물건 판매 후 빈 공간에 생기면 생산자에게 알려 준다. : 생산자는 물건이 비면 깨어난다 | ||
| * <p> | ||
| * 매장에서 물건 납품은 동시에 1명만 가능하다. : 납품 Syncronized | ||
| * <p> | ||
| * 매장에서 물건이 들어오면 소비자에게 알려 준다. : 빈 물건이 들어오면 깬다. | ||
| */ | ||
| 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; | ||
|
|
||
|
|
||
| public Store() { | ||
| this.goodsCount = new AtomicInteger(0); | ||
| this.consumerCount = new AtomicInteger(0); | ||
|
|
||
| } | ||
|
|
||
| public void enter() throws InterruptedException { | ||
|
|
||
| if (this.consumerCount.get() >= this.MAX_CONSUMER_COUNTS.get()) { | ||
| wait(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기서 wait을 해준다면 Main.java에서는 따로 조건을 검사하지 않고 스레드 풀이 일정 시간마다 생성만 되도록 구현할 수 있지 않을까욤?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞습니다! |
||
| } | ||
| this.consumerCount.addAndGet(1); | ||
| } | ||
|
|
||
| public void exit() { | ||
| this.consumerCount.addAndGet(-1); | ||
| } | ||
|
|
||
| public synchronized void buy() throws InterruptedException { | ||
| 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 (this.goodsCount.get() <= 0) { | ||
| wait(); | ||
| } | ||
| this.goodsCount.addAndGet(-1); | ||
| notifyAll(); | ||
| } | ||
|
|
||
| public synchronized int getGoodsCount() { | ||
| return this.goodsCount.intValue(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AtomicInteger 타입 안에 get이라는 메서드가 int value를 return해주는데 한번 더 get 메서드를 만드신 이유가 있을까요?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. producer에서 store에 접근하여 물건의 개수를 가져오기 위하여 메서드를 만들어주었습니다! |
||
| } | ||
|
|
||
| public synchronized int getConsumerCount() { | ||
| return this.consumerCount.intValue(); | ||
| } | ||
|
|
||
| public synchronized int getMAX_GOODS_COUNTS() { | ||
| return this.MAX_GOODS_COUNTS.intValue(); | ||
| } | ||
|
|
||
| public synchronized int getMAX_CONSUMER_COUNTS() { | ||
| return this.MAX_CONSUMER_COUNTS.intValue(); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package com.nhnacademy.Jminsoo.one; | ||
|
|
||
| import java.util.concurrent.ThreadLocalRandom; | ||
|
|
||
| public class Consumer implements Runnable { | ||
|
|
||
| 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); | ||
| } | ||
|
|
||
| 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 + " 마트 탈출!"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<Store> 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치킨, | ||
| 일반과자집; | ||
|
|
||
|
|
||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) { | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
쓰레드 풀 쓰셨네요 배워갈게요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 배워갑니다