Интернет магазин китайских планшетных компьютеров



Компьютеры - Scheduler

11 мая 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;
        }
    }
}


Просмотров: 1035


<<< Proxy (шаблон проектирования)
Single Thread Execution >>>