линия

Главная

суббота, 8 февраля 2025 г.

GO - пример многопоточной обработки

 

Одна из интересных задач на многопоточность в 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)
...
Все заказы обработаны, ресторан закрывается.

Комментариев нет:

Отправить комментарий