Интернет магазин китайских планшетных компьютеров |
|
Компьютеры - 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; } } } Просмотров: 1067
|