Одна из интересных задач на многопоточность в Go — это реализация симуляции работы ресторана, где несколько поваров готовят блюда, а официанты доставляют их клиентам. Задача будет включать использование горутин, каналов и синхронизацию для моделирования реального процесса.
Задача: Симуляция работы ресторана
Описание:
В ресторане работает несколько поваров и официантов.
Клиенты делают заказы, которые поступают в очередь.
Повара берут заказы из очереди и готовят блюда.
Официанты забирают готовые блюда и доставляют их клиентам.
Необходимо смоделировать этот процесс с использованием многопоточности.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | package main import ( "fmt" "math/rand" "sync" "time" ) // Order представляет заказ клиента type Order struct { ID int Dish string } // Chef готовит блюда func chef(id int, orders <-chan Order, readyDishes chan<- Order, wg *sync.WaitGroup) { defer wg.Done() for order := range orders { fmt.Printf("Повар %d готовит блюдо: %s (заказ %d)\n", id, order.Dish, order.ID) time.Sleep(time.Duration(rand.Intn(3)+1) * time.Second) // Время приготовления readyDishes <- order fmt.Printf("Повар %d завершил блюдо: %s (заказ %d)\n", id, order.Dish, order.ID) } } // Waiter доставляет блюда клиентам func waiter(id int, readyDishes <-chan Order, wg *sync.WaitGroup) { defer wg.Done() for dish := range readyDishes { fmt.Printf("Официант %d доставляет блюдо: %s (заказ %d)\n", id, dish.Dish, dish.ID) time.Sleep(time.Duration(rand.Intn(2)+1) * time.Second) // Время доставки fmt.Printf("Официант %d доставил блюдо: %s (заказ %d)\n", id, dish.Dish, dish.ID) } } func main() { rand.Seed(time.Now().UnixNano()) // Каналы для заказов и готовых блюд orders := make(chan Order, 10) readyDishes := make(chan Order, 10) // WaitGroup для поваров и официантов var chefsWg sync.WaitGroup var waitersWg sync.WaitGroup // Запуск поваров numChefs := 3 chefsWg.Add(numChefs) for i := 1; i <= numChefs; i++ { go chef(i, orders, readyDishes, &chefsWg) } // Запуск официантов numWaiters := 2 waitersWg.Add(numWaiters) for i := 1; i <= numWaiters; i++ { go waiter(i, readyDishes, &waitersWg) } // Клиенты делают заказы numOrders := 10 for i := 1; i <= numOrders; i++ { order := Order{ID: i, Dish: fmt.Sprintf("Блюдо %d", i)} fmt.Printf("Клиент сделал заказ: %s (заказ %d)\n", order.Dish, order.ID) orders <- order } // Закрываем канал заказов после того, как все заказы сделаны close(orders) // Ожидаем завершения всех поваров chefsWg.Wait() // Закрываем канал готовых блюд после завершения всех поваров close(readyDishes) // Ожидаем завершения всех официантов waitersWg.Wait() fmt.Println("Все заказы обработаны, ресторан закрывается.") } |
1 2 3 4 5 6 7 8 9 10 11 12 | Клиент сделал заказ: Блюдо 1 (заказ 1) Клиент сделал заказ: Блюдо 2 (заказ 2) Повар 1 готовит блюдо: Блюдо 1 (заказ 1) Повар 2 готовит блюдо: Блюдо 2 (заказ 2) Повар 1 завершил блюдо: Блюдо 1 (заказ 1) Официант 1 доставляет блюдо: Блюдо 1 (заказ 1) Повар 2 завершил блюдо: Блюдо 2 (заказ 2) Официант 2 доставляет блюдо: Блюдо 2 (заказ 2) Официант 1 доставил блюдо: Блюдо 1 (заказ 1) Официант 2 доставил блюдо: Блюдо 2 (заказ 2) ... Все заказы обработаны, ресторан закрывается. |
Комментариев нет:
Отправить комментарий