“嗨,阿米戈!”
“今天你将开始研究一个超级先进和有用的程序!这是一个电子菜单。看看:”
“太远了!这是干什么的?”
“你问这么多问题!看,你做,然后我们再谈。和特务商量,他会给你所有必要的指示。”
“队长大人!这么漂亮的艺术品我是造不出来的!”
“记住,你需要实现必要的业务逻辑。图片将由设计师创建。去见特工,你会一路想通的。”
“我会想办法的,先生!”
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 1)
Let's write a program to automate what happens in a restaurant.
We'll state the task like this: the restaurant manager wants the following:
1) each table has a tablet that can be used to place orders;
2) while an order is being prepared, the tablet shows ads.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 2)
1. We work with the console a lot. It's time to create a single point of interaction.
Create a ConsoleHelper class with a single BufferedReader, through which we will work with the console.
Remember, this class does not store any data or state, so all its methods will be static.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 3)
Now we can create orders. Let's make it so they are automatically sent to the cook.
There are many different ways to implement this functionality.
Read about the Observer pattern at http://en.wikipedia.org/wiki/Observer_pattern
It's already implemented in Java, and we're going to use it.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 4)
What do we have? The cook has prepared the dishes. It's time to take them away, but the waiter is unaware.
We need to notify the waiter that it's time to pick up the order from the kitchen.
This situation is similar to the previous task, so we'll use the Observer pattern again.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 5)
The cook currently prepares dishes instantaneously. In reality, cooking takes some time.
We need to calculate the time required to prepare the entire order, so we can then select commercials to fill the time.
1. Suppose we know the cooking time for each dish in minutes.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 6)
An order is created, prepared by the cook, and then carried out to the guest. We also calculate the time required to fill the order.
We'll consider the first part of the task complete.
Let's move on to the second: while the order is being prepared, ads should be shown on the tablet.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 7)
When choosing which class to start from, try to find one that is used by others, and which does not use anything.
In our case, this is the repository of advertising videos (AdvertisementStorage).
We decided that it would be the only one in the restaurant and made it a singleton.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 8)
It's time to describe the functionality of the AdvertisementManager class.
But first we're going to need some methods in the Advertisement class.
1. Create a long amountPerImpression field in the Advertisement class.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 9)
We need an exception that will help us handle the situation where we are unable to choose commercials.
1. Create an unchecked NoVideoAvailableException in the ad package.
2. Let's take a closer look at the void processVideos() method in AdvertisementManager.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 10)
Recursion is used when the algorithm for solving the problem is the same as the algorithm for solving part of the problem.
That's just what we have. We need to do a full search of all options and choose the best of them.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 11)
We've implemented the first two of the three features. You will recall that the first was automated order preparation,
the second was commercial selection, and the third is statistics for the manager. And that's our next step.
9
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 12)
We have several events:
*The cook prepared an order;
*The set of videos for an order has been chosen;
*There are no videos that can be shown while an order is prepared.
These are constants, so an enum is suitable for representing them.
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 13)
Let's return to the StatisticsManager class's record method. It should record events in a repository.
Let's create the repository :)
The repository has a 1-to-1 relationship with the manager, i.e. there is one manager and one repository per application.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 14)
1. Create a void put(EventDataRow data) method in StatisticsStorage.
2. To allow the put(EventDataRow data) method to add the data object to the map, we need the event type (EventType).
It would make sense for the event to store its type.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 15)
Let's think about what needs to be done so that the manager can view the following:
1) advertising revenues, grouped by day;
2) cook utilization (time spent working), grouped by day;
3) list of active videos and the number of remaining impressions for each.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 16)
Let's implement the first statistics item: advertising revenues, grouped by day.
1. In the VideosSelectedEventDataRow class, create a getter for the amount field.
In the OrderReadyEventDataRow class, create a getter for the cookName field.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 17)
Let's implement the third and fourth statistics items: the lists of active and inactive videos
It will be easier to do this with access to the video repository (AdvertisementStorage class).
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 18)
Currently, we have one tablet and 1 cook.
Let's create several tablets that will randomly generate orders, and we'll make two cooks.
1. In the Restaurant class, create a constant PRIVATE static int ORDER_CREATION_INTERVAL = 100.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 19)
We need to rework the main method.
First, let's make the parameters of our RandomOrderGeneratorTask constructors consistent.
Please make your method signature the same as mine:
public RandomOrderGeneratorTask(List tablets, int interval).
16
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 20)
Fix a bug: a tablet sends its orders to all known chefs.
Expected behavior: a tablet sends its orders to a queue, and an available cook takes orders from the queue.
There are two ways to implement this functionality:
1) Each tablet stores a reference to the queue and pushes new orders to it.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 21)
We continue to fix the bug.
Now all the orders arrive in the queue, but they don't reach the cooks.
We'll make OrderManager find any available cook and give it an order. To implement this logic,
we need a deamon thread.
32
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 22)
Unfortunately, the orders are still not being prepared in parallel. Here's how our thread from the previous task works.
It finds a cook, finds an order, gives the order to the cook using the startCookingOrder method, waits for the order to be prepared,
and only then moves on to the next order.
9
任务
Java Multithreading, 第 9 级, 课程 15
Restaurant (part 23)
That's it! You can make it beautiful on your own.
For example:
1. Threads usually use the ThreadLocalRandom class instead of Random. Refactor the code: replace Random with ThreadLocalRandom.
2. Make Waiter a task so that it works like a thread (remove Observer). Make a queue of prepared orders.