Список используемых источников
В чем разница между мьютексом, монитором и семафором: [Электронный ресурс]. 2019. URL: https://javarush.ru/groups/posts/2174-v-chem-raznica-mezhdu-mjhjuteksom-monitorom-i-semaforom.
Лабораторная работа № 2
«Пул потоков (Thread Pool)»
Задание:
Реализовать пул потоков для усовершенствования решения лабораторной работы № 1. В случаях, когда целевая система является многопроцессорной (или даже с одним многоядерным процессором, или с технологией HyperThreading) часто есть возможность ускорить обработку поступающих событий, выполняя ее параллельно. Для обработки каждого из событий используется отдельный поток; максимальное количество потоков, разумеется, ограничивается каким-то числом, например, 2, 4 или даже 10 – зависит от мощности системы. Т. к. создание потока – дорогостоящая операция, то обычно используют так называемый пул потоков: единожды созданные N потоков в своем нормальном состоянии простаивают, ожидая запроса на выполнение задачи, для решения которой они написаны. Когда такой запрос приходит, поток переходит в активное состояние, в котором он начинает потреблять процессорное время и решает задачу. По окончании обработки поток возвращается в состояние простоя. Если в момент возникновения очередной задачи свободных потоков нет, приходится, как правило, ждать, пока один из них освободится.
Описание работы приложения:
Лабораторная работа была реализована на языке программирования C#, т. к. он содержит все необходимые классы для реализации поставленной задачи. Был создан пул потоков-потребителей, теперь обработка очереди задач производится несколькими потоками. Для синхронизации общих данных использовался Mutex.
Разработанное GUI-приложение имеет одно окно с тремя текстовыми полями, одно из которых отображает отправленные «Производителем» сообщения, а другое – получаемые «Потребителем» сообщения. По нажатию на кнопку «Создать» начинается отправка «Производителем» сообщений и отображение их в первом текстовом поле «Буфер», в третьем текстовом поле «Результат» отображаются обработанные сообщения.
Пример работы приложения:
Рисунок 2 - Пример работы программы
Листинг программы:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RTS_Laba_1
{
public partial class Form1 : Form
{
int counter = 0;
string bufer = "";
Mutex mutex = new Mutex();
Mutex mutexConsumer = new Mutex();
Task produce;
Task consume;
Semaphore semaphore;
public Form1()
{
InitializeComponent();
ThreadPool.SetMaxThreads(10, 10);
semaphore = new Semaphore(3, 3);
//запуск Consume в потоке consume из пула
consume = Task.Run(Consume);
}
private void button1_Click(object sender, EventArgs e)
{
//запуск Produce в потоке produce из пула
produce = Task.Run(Produce);
}
void Produce()
{
mutex.WaitOne();
counter++;
bufer = $"Сообщение №{counter}";
Invoke(new Action(() =>
{
textBox1.Text = bufer;
}));
Thread.Sleep(50);
mutex.ReleaseMutex();
}
Queue<string> consumerBuffer = new Queue<string>(3);
void Consume()
{
while (!isClosed)
{
var isAdd = false;
mutex.WaitOne();
if (bufer.Length > 0)
{
if (consumerBuffer.Count < 5)
{
isAdd = true;
consumerBuffer.Enqueue(bufer);
// в UI потоке печатаем
Invoke(new Action(() =>
{
listBox2.Items.Clear();
listBox2.Items.AddRange(consumerBuffer.ToArray());
textBox1.Text = "";
}));
bufer = "";
}
}
mutex.ReleaseMutex();
if (isAdd)
{
Task.Run(() =>
{
semaphore.WaitOne();
Thread.Sleep(1200);
Invoke(new Action(() =>
{
mutexConsumer.WaitOne();
listBox1.Items.Add(consumerBuffer.Dequeue());
listBox2.Items.Clear();
listBox2.Items.AddRange(consumerBuffer.ToArray());
mutexConsumer.ReleaseMutex();
}));
semaphore.Release();
});
}
}
}
bool isClosed = false;
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
isClosed = true;
}
}
}
Вывод:
В ходе выполнения данной лабораторной работы были получены навыки реализации пула потоков, а также усовершенствовано решение лабораторной работы № 1.
