Skip to content
This repository was archived by the owner on Dec 26, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Consumer.java
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) {

}
}
}
25 changes: 25 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Main.java
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쓰레드 풀 쓰셨네요 배워갈게요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 배워갑니다

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);
// }
}

}
}

41 changes: 41 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Producer.java
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);
}
}
80 changes: 80 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/exercise/Store.java
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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 wait을 해준다면 Main.java에서는 따로 조건을 검사하지 않고 스레드 풀이 일정 시간마다 생성만 되도록 구현할 수 있지 않을까욤?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞습니다!
main의 조건을 삭제하였습니다!

}
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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AtomicInteger 타입 안에 get이라는 메서드가 int value를 return해주는데 한번 더 get 메서드를 만드신 이유가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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();
}
}

31 changes: 31 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/one/Consumer.java
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 + " 마트 탈출!");
}
}
21 changes: 21 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/one/Main.java
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);
}
}
}
61 changes: 61 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/one/Mart.java
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치킨,
일반과자집;


}

}
34 changes: 34 additions & 0 deletions Thread/src/main/java/com/nhnacademy/Jminsoo/one/Producer.java
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) {
}
}
}
Loading