Programator (model de design)

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită pe 28 mai 2019; verificările necesită 4 modificări .
Programator
Programator
Descris în Design Patterns Nu

Un planificator este un  model de proiectare paralel care oferă un mecanism pentru implementarea unei politici de planificare, dar nu depinde de nicio politică anume. Controlează ordinea în care firele de execuție ar trebui să execute codul secvențial, folosind un obiect care specifică în mod explicit secvența firelor de execuție în așteptare.

Motive

Exemplu de implementare

Exemplu C#

folosind System ; namespace Digital_Patterns.Concurrency.Sheduler { class Printer { private static Int32 mID = 0 ; Private Scheduler _scheduler = nou Scheduler (); public void Print ( JournalEntry journalEntry ) { Int32 id = ++ mID ; încercați { Console . WriteLine ( String . Format ( @"{0}: introduceți planificatorul" , id )); // apelul nu va fi executat până când obiectul Scheduler // decide că este timpul să imprime acest obiect JournalEntry _scheduler . Enter ( journalEntry ); Consola . WriteLine ( String . Format ( " @"{0}: start printing" , id )); încercați { //TODO Ceva journalEntry . Do ( id ); } în cele din urmă { // apelarea metodei Done îi spune Scheduler-ului că // obiectul JournalEntry a fost tipărit, iar un alt obiect // JournalEntry _scheduler poate fi lângă print . Gata (); Consola . WriteLine ( String . Format ( @"{0}: programator terminat" , id )); } } prinde ( Excepție ) {} } } }


folosind System ; folosind System.Collections.Generic ; folosind System.Threading ; namespace Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Instanțele de clasă din acest rol controlează procesarea obiectelor Request <see cref="JournalEntry"/> /// efectuată de obiectul Procesor <see cref="Printer „/> . Pentru a fi independentă de tipurile de cereri ///, clasa <see cref="Scheduler"/> nu trebuie să știe nimic despre clasa de solicitare pe care o gestionează. /// În schimb, accesează obiectele Request prin interfața pe care o implementează <see cref="ISchedulerOrdering"/> /// </summary> class Scheduler { /// <summary> /// Obiect de sincronizare a firelor /// < / rezumat> privat AutoResetEvent _event = nou AutoResetEvent ( fals ); /// <rezumat> /// Setat la null dacă resursa gestionată de Scheduler este inactivă. /// </summary> Private Thread _runningThread ; /// <summary> /// Threads și cererile lor în așteptare /// </summary> private Dictionary < Thread , ISchedulerOrdering > _waiting = new Dictionary < Thread , ISchedulerOrdering >(); /// <summary> /// Metoda <see cref="Enter"/> este apelată înainte ca firul de execuție să înceapă să folosească resursa gestionată. /// Metoda nu este executată până când resursa gestionată este eliberată și obiectul <see cref="Sheduler"/> /// decide că coada de execuție a acestei solicitări a sosit /// </summary> /// <param name ="s"></param> public void Enter ( ISchedulerOrdering s ) { var thisThread = Thread . CurrentThread ; lock ( this ) { // Stabilește dacă planificatorul este ocupat if ( _runningThread == null ) { // Începe imediat executarea cererii primite _runningThread = thisThread ; întoarcere ; } _așteaptă . Adăugați ( acestThread , s ); } lock ( thisThread ) { // Blocați firul până când planificatorul decide să îl transforme în firul curent în timp ce ( thisThread != _runningThread ) { _event . waitone (); _eveniment . set (); // lasă alte fire să își verifice starea Thread . somn ( 1 ); } _eveniment . resetare (); } blocare ( asta ) { _așteaptă . Eliminați ( acest fir ); } } /// <summary> /// Apelarea metodei <see cref="Done"/> indică faptul că firul curent s-a încheiat /// și resursa gestionată a fost eliberată /// </summary> public void Done () { lock ( this ) { if ( _runningThread != Thread . CurrentThread ) throw new ThreadStateException ( @"Wrong Thread" ); Int32 waitCount = _waiting . numără ; if ( waitCount <= 0 ) { _runningThread = null ; } else if ( waitCount == 1 ) { _runningThread = _waiting . primul (). cheie ; _așteaptă . Eliminați ( _runningThread ); _eveniment . set (); } else { var next = _waiting . primul (); foreach ( var wait in _waiting ) { if ( wait . Value . ScheduleBefore ( next . Value )) { next = wait ; } } _runningThread = următorul . cheie ; _eveniment . set (); } } } } /// <summary> /// Clasa de ajutor /// </summary> clasă parțială statică ConvertTo { /// <summary> /// Obține primul element al colecției /// </summary> /// < param name= "colecție"></param> /// <returns></returns> public static KeyValuePair < ​​​​Thread , ISchedulerOrdering > First ( acest Dicționar < Thread , ISchedulerOrdering > collection ) { foreach ( var item in collection ) { returnare articol ; } aruncă o nouă excepție ArgumentException (); } } }


folosind System ; namespace Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Dacă mai multe operațiuni așteaptă pentru a accesa o resursă, clasa <see cref="Scheduler"/> /// folosește această interfață pentru a determina ordinea în care operațiunile trebuie efectuate. /// </summary> interfață ISchedulerOrdering { Boolean ScheduleBefore ( ISchedulerOrdering s ); } }


folosind System ; folosind System.Threading ; namespace Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Exemplu de cod de clasă <see cref="JournalEntry"/> care urmează să fie /// tipărit de <see cref="Printer"/> /// < /summary > clasa JournalEntry : ISchedulerOrdering { private static DateTime mTime = DateTime . acum ; private DateTime _time ; /// <summary> /// Returnează ora de creare a acestui obiect /// </summary> public DateTime Time { get { return _time ; } } private String_msg ; _ public JournalEntry ( șir de mesaje ) { mTime = mTime . AddSeconds ( 1 ); _time = mTime ; _msg = msg ; } public void Do ( Int32 id ) { Consolă . WriteLine ( String . Format ( @"{0}: Începeți să faceți: {1} : {2}" , id , _time , _msg )); fir . Somn ( 1000 ); Consola . WriteLine ( String . Format ( @"{0}: Finish do : {1} : {2}" , id , _time , _msg )); } /// <rezumat> /// Returnează adevărat dacă această solicitare /// ar trebui procesată înainte de această solicitare. /// </summary> /// <param name="s"></param> /// <returns></returns> public Boolean ScheduleBefore ( ISchedulerOrdering s ) { dacă ( s este JournalEntry ) { var otherJournalEntry = ( JournalEntry ) s ; return ( acest . Time < otherJournalEntry . Time ); } return false ; } } }


folosind System ; folosind System.Threading ; namespace Digital_Patterns.Concurrency.Sheduler { public class Example01 { private Printer _printer ; public void Run () { Consolă . WriteLine ( "Apăsați orice tastă pentru a începe și apăsați din nou pentru a termina" ); Consola . ReadKey (); _printer = imprimantă nouă (); noua discuție ( Fila1 ). Start (); noua fire ( Fila2 ). Start (); noua discuție ( Fila3 ). Start (); Consola . ReadKey (); } private void Thread1 () { var msg1 = new JournalEntry ( @"Cumpărați cu taxă 5,45 USD" ); var msg2 = new JournalEntry ( @"Cumpara bomboane 1,05 USD" ); var msg3 = new JournalEntry ( "Cumpara ciocolata 3,25 USD" ); _imprimanta . Imprimare ( msg1 ); _imprimanta . Imprimare ( msg2 ); _imprimanta . Imprimare ( msg3 ); } private void Thread2 () { var msg4 = new JournalEntry ( @"Cumpărați carte poștală 2,05 USD" ); var msg5 = new JournalEntry ( @"Cumpara gerland 37,78 USD" ); _imprimanta . Imprimare ( msg4 ); _imprimanta . Imprimare ( msg5 ); } private void Thread3 () { var msg6 = new JournalEntry ( @"Buy ball 30.06 USD" ); var msg7 = new JournalEntry ( @"Cumpara conducta 1,83 USD" ); _imprimanta . Imprimare ( msg6 ); _imprimanta . Imprimare ( msg7 ); } } }


folosind System ; folosind Digital_Patterns.Concurrency.Sheduler ; namespace Digital_Patterns { class Program { static void Main ( șir [] args ) { nou Exemplu01 (). alerga (); Consola . WriteLine ( "Apăsați orice tastă pentru final" ); Consola . ReadKey (); } } }

Link -uri

  • Mark Grand. Modele în Java Volumul 1: Un catalog de modele de design reutilizabile ilustrate cu UML. - Wiley & Sons, 1998. - 480 p. — ISBN 0471258393 . (vezi rezumatul  (în engleză) )