Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабораторные работы / Лабораторная работа 5 / ПКРПСиБД LAB5 Бочаров И.А

..docx
Скачиваний:
20
Добавлен:
28.06.2014
Размер:
101.88 Кб
Скачать

Национальный исследовательский институт

Московский Энергетический Институт (Технический Университет)

Институт автоматики и вычислительной техники

Кафедра Прикладной математики

Лабораторная работа №5

по дисциплине:

Проектирование крупных распределенных программных систем и баз данных

тема: «Разработка одного из шаблонов параллельного программирования»

вариант №5 – «Scheduler/Планировщик»

Выполнил:

Бочаров Иван Андреевич

Проверил:

к.т.н., доц. Куриленко Иван Евгеньевич

Москва

2012 г.

Шаблон проектирования «Планировщик»

Категория шаблона

Шаблон проектирования «Планировщик» относится к шаблонам параллельного программирования.

Описание шаблона

Планировщик - паттерн параллельного программирования, который используется для обеспечения явного контроля за ситуацией, когда разные потоки могут выполнять куски однопоточного кода (операции записи в файл и т.д.).

Суть паттерна заключается в создании объекта, который явным образом ставит в очередь ожидающие ресурс потоки.

Уместность применения

Шаблон следует применять, если:

  • Несколько потоков могут потребовать доступа к ресурсу одновременно, и только один из них может в конкретный момент осуществить доступ к ресурсу

  • Требуется обеспечение доступа потоков к ресурсу в строго определенном порядке

Преимущества шаблона

При использовании шаблона «Планировщик» объект планировщика независим от политики, по которой упорядочиваются потоки, что упрощает повторное использование кода.

Реализация

MobileAccount.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace SchedulerPattern

{

class MobileAccount

{

private static int transactionID;

private Scheduler scheduler = new Scheduler();

private int balance = 0;

public void Handle(Transaction transaction)

{

int id = ++transactionID;

try

{

Console.WriteLine(String.Format(@"Transaction #{0}: enter scheduler", id));

scheduler.Enter(transaction);

Console.WriteLine(String.Format(@"Transaction #{0}: start handling", id));

try

{

transaction.Do(id);

balance += transaction.Chng;

}

finally

{

scheduler.Done();

Console.WriteLine(String.Format(@"Transaction #{0}: done! Account balance is {1}", id, balance));

}

}

catch (Exception) { }

}

}

}

Scheduler.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

namespace SchedulerPattern

{

class Scheduler

{

private AutoResetEvent evnt = new AutoResetEvent(false);

private Thread runningThread;

private Dictionary<Thread, IOrdering> waiting = new Dictionary<Thread, IOrdering>();

public void Enter(IOrdering s)

{

var thisThread = Thread.CurrentThread;

lock (this)

{

if (runningThread == null)

{

runningThread = thisThread;

return;

}

waiting.Add(thisThread, s);

}

lock (thisThread)

{

while (thisThread != runningThread)

{

evnt.WaitOne();

evnt.Set();

Thread.Sleep(1);

}

evnt.Reset();

}

lock (this)

{

waiting.Remove(thisThread);

}

}

public void Done()

{

lock (this)

{

if (runningThread != Thread.CurrentThread)

throw new ThreadStateException(@"Wrong Thread");

int waitCount = waiting.Count;

if (waitCount <= 0)

{

runningThread = null;

}

else if (waitCount == 1)

{

runningThread = waiting.First().Key;

waiting.Remove(runningThread);

evnt.Set();

}

else

{

var next = waiting.First();

foreach (var wait in waiting)

{

if (wait.Value.ScheduleBefore(next.Value))

{

next = wait;

}

}

runningThread = next.Key;

evnt.Set();

}

}

}

}

static partial class ConvertTo

{

public static KeyValuePair<Thread, IOrdering> First(this Dictionary<Thread, IOrdering> collection)

{

foreach (var item in collection)

{

return item;

}

throw new ArgumentException();

}

}

}

Transaction.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

namespace SchedulerPattern

{

class Transaction : IOrdering

{

private static DateTime mTime = DateTime.Now;

private DateTime time;

public DateTime Time { get { return time; } }

private int chng;

public int Chng

{

get { return chng; }

}

public Transaction(int chng)

{

mTime = mTime.AddSeconds(1);

time = mTime;

this.chng = chng;

}

public void Do(int id)

{

Console.WriteLine(String.Format(@"Transaction #{0}: Start : {1} : Balance change: {2} roubles", id, time, chng));

Thread.Sleep(1000);

Console.WriteLine(String.Format(@"Transaction #{0}: Finish : {1} : Balance change: {2} roubles", id, time, chng));

}

public Boolean ScheduleBefore(IOrdering s)

{

if (s is Transaction)

{

var otherTransaction = (Transaction)s;

return (this.Time < otherTransaction.Time);

}

return false;

}

}

}

IOrdering.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace SchedulerPattern

{

interface IOrdering

{

Boolean ScheduleBefore(IOrdering s);

}

}

UML-диаграмма классов

Диаграмма последовательности

Литература

  1. http://en.wikipedia.org/wiki/Scheduler_pattern

  2. http://ru.wikipedia.org/wiki/Scheduler