-
Notifications
You must be signed in to change notification settings - Fork 103
Lesson 62 (wait notify) #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: for-pr
Are you sure you want to change the base?
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,47 @@ | ||
| package com.walking.lesson62_wait_notify.task1.model; | ||
|
|
||
| public class Message { | ||
| private String message; | ||
| private boolean isReceived = false; | ||
|
|
||
| public Message() { | ||
| } | ||
|
|
||
| public String getMessage() { | ||
| return message; | ||
| } | ||
|
|
||
| public synchronized String receive() { | ||
| while (!isReceived) { | ||
| try { | ||
| wait(); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
| } | ||
| } | ||
|
|
||
| isReceived = false; | ||
| String receivedMessage = message; | ||
|
|
||
| notifyAll(); | ||
|
|
||
| return receivedMessage; | ||
| } | ||
|
|
||
| public synchronized void send(String message) { | ||
| while (isReceived) { | ||
| try { | ||
| wait(); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
|
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.message = message; | ||
| isReceived = true; | ||
|
|
||
| notifyAll(); | ||
| } | ||
|
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. Размещать функциональность отправки и получения сообщения в самом Message - грубая ошибка. Завтра я захочу логику отправки-получения переделать через брокер сообщений или еще как-то - почему я при этом должен менять саму сущность "сообщение"? 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. То есть текущий класс надо либо переименовать, либо выделить класс логики, который будет отвечать за обработку сообщения 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. Но я бы просто вынес отправку и получение в логику отдельных сущностей - тогда любой потенциальный полиморфизм будет реализовать проще |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.walking.lesson62_wait_notify.task1.model; | ||
|
|
||
| import java.util.function.Consumer; | ||
|
|
||
| public class MessageReceiver implements Runnable { | ||
| private final Message message; | ||
| private final Consumer<String> stringConsumer; | ||
|
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. Интересная идея. Но не всегда корректная на практике. В данном случае класс, создающий сущность получателя (или отправителя), должен знать, что будет происходить при отправке или получении. Чаще всего это не будет его ответственностью |
||
|
|
||
| public MessageReceiver(Message message, Consumer<String> stringConsumer) { | ||
| this.message = message; | ||
| this.stringConsumer = stringConsumer; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| String receivedMessage = message.receive(); | ||
|
|
||
| while (!"finish".equalsIgnoreCase(receivedMessage)) { | ||
| stringConsumer.accept(receivedMessage); | ||
|
|
||
| receivedMessage = message.receive(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.walking.lesson62_wait_notify.task1.model; | ||
|
|
||
| import java.util.function.Supplier; | ||
|
|
||
| public class MessageSender implements Runnable { | ||
| private final Message message; | ||
| private final Supplier<String> stringSupplier; | ||
|
|
||
| public MessageSender(Message message, Supplier<String> stringSupplier) { | ||
| this.message = message; | ||
| this.stringSupplier = stringSupplier; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| while (!"finish".equalsIgnoreCase(message.getMessage())) { | ||
| message.send(stringSupplier.get()); | ||
| } | ||
| } | ||
| } | ||
|
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. Вердикт: технические решения местами интересные, с зонами ответственности классов перемудрил |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package com.walking.lesson62_wait_notify.task2.model; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.Random; | ||
| import java.util.function.IntSupplier; | ||
|
|
||
| public class Customer implements Runnable { | ||
| private final Depot depot; | ||
| private final IntSupplier intSupplier; | ||
| private final Random random = new Random(); | ||
|
|
||
| public Customer(Depot depot, IntSupplier intSupplier) { | ||
| this.depot = depot; | ||
| this.intSupplier = intSupplier; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| int shortage = 1; | ||
|
|
||
| while (!Thread.currentThread() | ||
| .isInterrupted()) { | ||
| try { | ||
| Thread.sleep(Duration.ofSeconds(random.nextInt(1, 4))); | ||
|
|
||
| while (--shortage < 1) { | ||
| shortage = intSupplier.getAsInt(); | ||
| } | ||
|
|
||
| shortage = depot.tryPurchase(shortage); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package com.walking.lesson62_wait_notify.task2.model; | ||
|
|
||
| import com.walking.lesson62_wait_notify.task2.util.Logger; | ||
|
|
||
| public class Depot { | ||
| public final static int MAX_STOCK_VALUE = 100; | ||
| public final static int STOP_PURCHASE_STOCK_VALUE = 0; | ||
| public final static int STOP_SUPPLY_STOCK_VALUE = 100; | ||
| public final static int START_SUPPLY_STOCK_VALUE = 25; | ||
|
|
||
| private final Logger logger; | ||
|
|
||
| private boolean isRequiredSupply = true; | ||
| private int stock; | ||
|
|
||
| public Depot(Logger logger) { | ||
| this.logger = logger; | ||
| } | ||
|
|
||
| public int getStock() { | ||
| return stock; | ||
| } | ||
|
|
||
| public synchronized int trySupply(int count) { | ||
| while (!isRequiredSupply) { | ||
| try { | ||
| wait(); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
| } | ||
| } | ||
|
|
||
| logger.log("Остаток товаров - %d. %s пытается поставить %d товаров.".formatted(stock, Thread.currentThread() | ||
| .getName(), count)); | ||
|
|
||
| stock += count; | ||
| int surplus = 0; | ||
|
|
||
| inspectCapacity(); | ||
|
|
||
| if (stock > MAX_STOCK_VALUE) { | ||
| surplus = stock - MAX_STOCK_VALUE; | ||
| stock = MAX_STOCK_VALUE; | ||
|
|
||
| logger.log("Склад заполнен. Избыток товаров возвращен поставщику - %s.".formatted(surplus)); | ||
| } | ||
|
|
||
| notifyAll(); | ||
|
|
||
| return surplus; | ||
| } | ||
|
|
||
| public synchronized int tryPurchase(int count) { | ||
| if (stock == STOP_PURCHASE_STOCK_VALUE) { | ||
| try { | ||
| wait(); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
| } | ||
| } | ||
|
|
||
| logger.log("Остаток товаров - %d. %s пытается купить %d товаров.".formatted(stock, Thread.currentThread() | ||
|
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. не логичнее в методы логгера докрутить varargs и дать возможность передавать параметры для форматирования? Чтобы не форматировать вручную в бизнес-коде |
||
| .getName(), count)); | ||
|
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. лишний перенос |
||
|
|
||
| int balance = stock - count; | ||
| int shortage = 0; | ||
|
|
||
| if (balance >= STOP_PURCHASE_STOCK_VALUE) { | ||
| stock = balance; | ||
|
|
||
| inspectCapacity(); | ||
| } else { | ||
| shortage = count; | ||
|
|
||
| logger.log("Склад пуст. Не хватило товаров для продажи - %s.".formatted(shortage)); | ||
| } | ||
|
|
||
| notifyAll(); | ||
|
|
||
| return shortage; | ||
| } | ||
|
|
||
| private void inspectCapacity() { | ||
| if (stock <= START_SUPPLY_STOCK_VALUE && !isRequiredSupply) { | ||
| isRequiredSupply = true; | ||
| } else if (stock >= STOP_SUPPLY_STOCK_VALUE && isRequiredSupply) { | ||
| isRequiredSupply = false; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package com.walking.lesson62_wait_notify.task2.model; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.Random; | ||
| import java.util.function.IntSupplier; | ||
|
|
||
| public class Provider implements Runnable { | ||
| private final Depot depot; | ||
| private final IntSupplier intSupplier; | ||
| private final Random random = new Random(); | ||
|
|
||
| public Provider(Depot depot, IntSupplier intSupplier) { | ||
| this.depot = depot; | ||
| this.intSupplier = intSupplier; | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| int surplus = 0; | ||
|
|
||
| while (!Thread.currentThread() | ||
| .isInterrupted()) { | ||
|
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. лишний перенос |
||
| try { | ||
| while (surplus == 0) { | ||
| surplus = intSupplier.getAsInt(); | ||
| } | ||
|
|
||
| Thread.sleep(Duration.ofSeconds(random.nextInt(1, 4))); | ||
|
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. не помню в условии требований к простою у покупателей или поставщиков |
||
|
|
||
| surplus = depot.trySupply(surplus); | ||
| } catch (InterruptedException e) { | ||
| Thread.currentThread() | ||
| .interrupt(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
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.
зачем явно прописывать конструктор по умолчанию?