Интернет магазин китайских планшетных компьютеров |
|
Компьютеры - Scheduler11 мая 2011Планировщик шаблон проектирования, обеспечивающий механизм реализации политики планирования, но при этом не зависящий ни от одной конкретной политики. Управляет порядком, в соответствии с которым потокам предстоит выполнить последовательный код, используя для этого объект, который явным образом задаёт последовательность ожидающих потоков. Мотивы
Пример реализацииПример C#
using System;
namespace Digital_Patterns.Concurrency.Sheduler
{
class Printer
{
private static Int32 mID = 0;
private Scheduler _scheduler = new Scheduler;
public void Print
{
Int32 id = ++mID;
try
{
Console.WriteLine);
// вызов не выполнится до тех пор, пока объект Scheduler не решит,
// что подошла очередь распечатать этот объект JournalEntry
_scheduler.Enter;
Console.WriteLine);
try
{
//TODO Something
journalEntry.Do;
}
finally
{
// вызов метода Done говорит Scheduler о том, что объект JournalEntry
// распечатан, и может подойти очередь вывода на печать другого объекта
// JournalEntry
_scheduler.Done;
Console.WriteLine);
}
}
catch {}
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
namespace Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Экземпляры классов в этой роли управляют обработкой объектов Request <see cref="JournalEntry"/>,
/// выполняемой объектом Processor <see cref="Printer"/>. Чтобы быть независимыми от типов
/// запросов, класс <see cref="Scheduler"/> не должен ничего знать об управляемом им классе Requect.
/// Вместо этого он осущуствляет доступ к объектам Request через реализуемый ими интерфейс <see cref="ISchedulerOrdering"/>
/// </summary>
class Scheduler
{
/// <summary>
/// Объект синхронизации потоков
/// </summary>
private AutoResetEvent _event = new AutoResetEvent;
/// <summary>
/// Устанавливается в null, если управляемый объектом Scheduler ресурс не занят.
/// </summary>
private Thread _runningThread;
/// <summary>
/// Потоки и их запросы ожидающие выполнения
/// </summary>
private Dictionary<Thread, ISchedulerOrdering> _waiting = new Dictionary<Thread, ISchedulerOrdering>;
/// <summary>
/// Метод <see cref="Enter"/> вызывается перед тем, как поток начнет использовать уравляемый ресурс.
/// Метод не выполняется до тех пор пока управляемый ресур не освободиться и объект <see cref="Sheduler"/>
/// не примет решение, что подошла очередь выполнения этого запроса
/// </summary>
/// <param name="s"></param>
public void Enter
{
var thisThread = Thread.CurrentThread;
lock
{
// Определяем не занят ли планировщик
if
{
// Немедленно начинаем выполнение поступившего запроса
_runningThread = thisThread;
return;
}
_waiting.Add;
}
lock
{
//Блокируем поток до тех пор, пока планировщик не решит сделать его текущим
while
{
_event.WaitOne;
_event.Set; // даем возможность другим потокам проверить своё состояние
Thread.Sleep;
}
_event.Reset;
}
lock
{
_waiting.Remove;
}
}
/// <summary>
/// Вызов метода <see cref="Done"/> указывает на то, что текущий поток завершил работу
/// и управляемый ресурс освободился
/// </summary>
public void Done
{
lock
{
if
throw new ThreadStateException;
Int32 waitCount = _waiting.Count;
if
{
_runningThread = null;
}
else if
{
_runningThread = _waiting.First.Key;
_waiting.Remove;
_event.Set;
}
else
{
var next = _waiting.First;
foreach
{
if)
{
next = wait;
}
}
_runningThread = next.Key;
_event.Set;
}
}
}
}
/// <summary>
/// Вспомогательный класс
/// </summary>
static partial class ConvertTo
{
/// <summary>
/// Получить первый элемент коллекции
/// </summary>
/// <param name="collection"></param>
/// <returns></returns>
public static KeyValuePair<Thread, ISchedulerOrdering> First
{
foreach
{
return item;
}
throw new ArgumentException;
}
}
}
using System;
namespace Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Если несколько операций ожидают доступа к ресурсу, класс<see cref="Scheduler"/> использует
/// данный интерфейс для определения порядка выполнения операций.
/// </summary>
interface ISchedulerOrdering
{
Boolean ScheduleBefore;
}
}
using System;
using System.Threading;
namespace Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Примерный код класса <see cref="JournalEntry"/>, который должен быть
/// распечатан классом <see cref="Printer"/>
/// </summary>
class JournalEntry : ISchedulerOrdering
{
private static DateTime mTime = DateTime.Now;
private DateTime _time;
/// <summary>
/// Возвращает время создания этого объекта
/// </summary>
public DateTime Time { get { return _time; } }
private String _msg;
public JournalEntry
{
mTime = mTime.AddSeconds;
_time = mTime;
_msg = msg;
}
public void Do
{
Console.WriteLine);
Thread.Sleep;
Console.WriteLine);
}
/// <summary>
/// Возвращает true, если данный запрос должен
/// обрабатываться перед этим запросом.
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public Boolean ScheduleBefore
{
if
{
var otherJournalEntry = s;
return ;
}
return false;
}
}
}
using System;
using System.Threading;
namespace Digital_Patterns.Concurrency.Sheduler
{
public class Example01
{
private Printer _printer;
public void Run
{
Console.WriteLine;
Console.ReadKey;
_printer = new Printer;
new Thread.Start;
new Thread.Start;
new Thread.Start;
Console.ReadKey;
}
private void Thread1
{
var msg1 = new JournalEntry;
var msg2 = new JournalEntry;
var msg3 = new JournalEntry;
_printer.Print;
_printer.Print;
_printer.Print;
}
private void Thread2
{
var msg4 = new JournalEntry;
var msg5 = new JournalEntry;
_printer.Print;
_printer.Print;
}
private void Thread3
{
var msg6 = new JournalEntry;
var msg7 = new JournalEntry;
_printer.Print;
_printer.Print;
}
}
}
using System;
using Digital_Patterns.Concurrency.Sheduler;
namespace Digital_Patterns
{
class Program
{
static void Main
{
new Example01.Run;
Console.WriteLine;
Console.ReadKey;
}
}
}
Просмотров: 1196
|