Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active April 2, 2026 18:34
Show Gist options
  • Select an option

  • Save sunmeat/1e2855aa2b4f28b7ccec92de5c1686c0 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/1e2855aa2b4f28b7ccec92de5c1686c0 to your computer and use it in GitHub Desktop.
concurrent collections
using System.Collections.Concurrent;
using System.Text;
class Program
{
static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
// === ConcurrentDictionary: потокобезпечний список замовлень ===
var orders = new ConcurrentDictionary<int, string>();
var orderWorker1 = new Thread(() =>
{
Console.WriteLine("[Менеджер] Додає замовлення...");
orders.TryAdd(101, "Прийнято в обробку");
/* Add (у звичайному Dictionary)
- додає елемент;
- якщо ключ вже існує → кидає виняток (ArgumentException).
TryAdd (у ConcurrentDictionary)
- намагається додати елемент;
- якщо ключ уже існує → нічого не робить і повертає false, замість винятку;
- якщо додавання вдалося → повертає true
Така логіка дуже зручна у багатопоточності, де кілька потоків можуть одночасно
працювати з колекцією, і винятки при зіткненні були б зайвим навантаженням! */
orders.TryAdd(102, "Прийнято в обробку");
orders.TryAdd(103, "Прийнято в обробку");
orders.TryAdd(104, "Прийнято в обробку");
});
var orderWorker2 = new Thread(() =>
{
Thread.Sleep(100);
Console.WriteLine("[Система] Оновлює статус замовлень...");
orders.AddOrUpdate(101, "Відправлено", (key, oldValue) => "Відправлено");
orders.AddOrUpdate(102, "Відправлено", (key, oldValue) => "Відправлено");
orders.TryRemove(104, out _);
});
orderWorker1.Start();
orderWorker2.Start();
orderWorker1.Join();
orderWorker2.Join();
Console.WriteLine($"[Система] Підсумковий стан замовлень: {string.Join(", ", orders)}");
// === ConcurrentQueue: потокобезпечна черга завдань ===
var taskQueue = new ConcurrentQueue<string>();
var taskProducer1 = new Thread(() =>
{
taskQueue.Enqueue("Пакування замовлення 101");
taskQueue.Enqueue("Пакування замовлення 102");
taskQueue.Enqueue("Пакування замовлення 103");
});
var taskProducer2 = new Thread(() =>
{
taskQueue.Enqueue("Доставка замовлення 101");
taskQueue.Enqueue("Доставка замовлення 102");
});
taskProducer1.Start();
taskProducer2.Start();
taskProducer1.Join();
taskProducer2.Join();
while (taskQueue.TryDequeue(out var task)) // інлайн-змінна, скорочення string task; while (taskQueue.TryDequeue(out task))
{
Console.WriteLine($"[Логістика] Виконуємо завдання: {task}");
}
// === ConcurrentStack: потокобезпечний склад ===
var warehouse = new ConcurrentStack<int>();
var supplier1 = new Thread(() =>
{
warehouse.Push(5001);
warehouse.Push(5002);
warehouse.Push(5003);
Console.WriteLine("[Постачальник] Привіз три товари");
});
var supplier2 = new Thread(() =>
{
warehouse.Push(6001);
warehouse.Push(6002);
Console.WriteLine("[Постачальник] Привіз два товари");
});
supplier1.Start();
supplier2.Start();
supplier1.Join();
supplier2.Join();
while (warehouse.TryPop(out int item))
{
Console.WriteLine($"[Склад] Взяли товар {item} для збирання замовлення");
}
// === ConcurrentBag: пул працівників ===
var workers = new ConcurrentBag<string>();
// застосовується:
// - для зберігання великої кількості об'єктів, якими користуються різні потоки (наприклад, кешування даних чи збір об'єктів)
// - коли порядок вилучення елементів не має значення (наприклад, пул об'єктів)
// - якщо один потік частіше додає, а потім той самий потік забирає (у цьому випадку ConcurrentBag<T> працює швидше за інші структури)
var workerThread1 = new Thread(() =>
{
workers.Add("Працівник 1");
workers.Add("Працівник 2");
Console.WriteLine("[Відділ кадрів] Найняли двох працівників");
});
var workerThread2 = new Thread(() =>
{
Thread.Sleep(50);
workers.Add("Працівник 3");
workers.Add("Працівник 4");
Console.WriteLine("[Відділ кадрів] Найняли ще двох працівників");
});
workerThread1.Start();
workerThread2.Start();
workerThread1.Join();
workerThread2.Join();
Console.WriteLine("[Система] Підсумковий список працівників:");
foreach (var worker in workers)
{
Console.WriteLine($" - {worker}");
}
// === емуляція роботи магазину ===
var rnd = new Random();
var processingOrders = new ConcurrentQueue<int>();
var processOrdersThread = new Thread(() =>
{
foreach (var order in orders.Keys)
{
processingOrders.Enqueue(order);
Console.WriteLine($"[Система] Замовлення {order} відправлено на обробку");
Thread.Sleep(rnd.Next(50, 150));
}
});
var completeOrdersThread = new Thread(() =>
{
Thread.Sleep(100);
while (processingOrders.TryDequeue(out int order))
{
orders[order] = "Завершено";
Console.WriteLine($"[Система] Замовлення {order} оброблено та завершено");
Thread.Sleep(rnd.Next(50, 150));
}
});
processOrdersThread.Start();
completeOrdersThread.Start();
processOrdersThread.Join();
completeOrdersThread.Join();
Console.WriteLine("\n=== Підсумковий стан системи ===");
Console.WriteLine($"Замовлення: {string.Join(", ", orders)}");
Console.WriteLine($"Завдань у черзі: {taskQueue.Count}");
Console.WriteLine($"Залишилось товарів на складі: {warehouse.Count}");
Console.WriteLine($"Працівників: {workers.Count}");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment