Planlægger (designmønster)

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 28. maj 2019; checks kræver 4 redigeringer .
Planlægger
Planlægger
Beskrevet i Design Patterns Ikke

En planlægger er et  parallelt designmønster, der giver en mekanisme til at implementere en planlægningspolitik, men som ikke afhænger af nogen bestemt politik. Styrer rækkefølgen, som tråde skal udføre sekventiel kode i, ved hjælp af et objekt, der eksplicit specificerer rækkefølgen af ​​ventende tråde.

Motiver

Implementeringseksempel

C# eksempel

bruger System ; navneområde Digital_Patterns.Concurrency.Sheduler { class Printer { private static Int32 mID = 0 ; private Scheduler _scheduler = ny Scheduler (); public void Print ( JournalEntry journalEntry ) { Int32 id = ++ mID ; prøv { Konsol . WriteLine ( String . Format ( @"{0}: enter scheduler" , id )); // opkaldet vil ikke blive udført, før Scheduler-objektet // beslutter, at det er tid til at udskrive dette JournalEntry _scheduler-objekt . Enter ( journalindgang ); Konsol . WriteLine ( String . Format ( @"{0}: start printing" , id )); prøv { //TODO Something journalEntry . Gør ( id ); } endelig { // kalder du Done-metoden, fortæller Scheduler, at // JournalEntry-objektet er blevet udskrevet, og et andet // JournalEntry _scheduler- objekt kan være ved siden af ​​print . Udført (); Konsol . WriteLine ( String . Format ( @"{0}: done scheduler" , id )); } } catch ( Undtagelse ) {} } } }


bruger System ; ved hjælp af System.Collections.Generic ; ved hjælp af System.Threading ; navneområde Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Klasseforekomster i denne rolle styrer behandlingen af ​​Request-objekter <see cref="JournalEntry"/> /// udført af Processor-objektet <see cref="Printer "/> . For at være uafhængig af /// anmodningstyper behøver klassen <see cref="Scheduler"/> ikke at vide noget om den Request-klasse, den administrerer. /// I stedet får den adgang til Request-objekter via den grænseflade, de implementerer <see cref="ISchedulerOrdering"/> /// </summary> class Scheduler { /// <summary> /// Trådsynkroniseringsobjekt /// < / summary> private AutoResetEvent _event = new AutoResetEvent ( false ); /// <resumé> /// Sæt til null, hvis den ressource, der administreres af planlæggeren, er inaktiv. /// </summary> privat tråd _runningThread ; /// <summary> /// Tråde og deres anmodninger venter /// </summary> privat ordbog < Thread , ISchedulerOrdering > _waiting = new Dictionary < Thread , ISchedulerOrdering >(); /// <resumé> /// <see cref="Enter"/> metoden kaldes før tråden begynder at bruge den administrerede ressource. /// Metoden udføres ikke, før den administrerede ressource er frigivet, og <see cref="Sheduler"/> objektet /// beslutter, at denne anmodnings eksekveringskø er ankommet /// </summary> /// <param name ="s"></param> public void Enter ( ISchedulerOrdering s ) { var thisThread = Thread . CurrentThread ; lock ( this ) { // Bestem om planlæggeren er optaget if ( _runningThread == null ) { // Start med det samme at udføre den indkommende anmodning _runningThread = thisThread ; returnere ; } _venter . Tilføj ( denne tråd , s ); } lock ( thisThread ) { // Bloker tråden indtil planlæggeren beslutter at gøre den til den aktuelle tråd mens ( thisThread != _runningThread ) { _event . waitone (); _begivenhed . sæt (); // lad andre tråde kontrollere deres tilstand Tråd . søvn ( 1 ); } _begivenhed . nulstil (); } lås ( dette ) { _waiting . Fjern ( denne tråd ); } } /// <summary> /// Kaldning af <see cref="Done"/>-metoden indikerer, at den aktuelle tråd er afsluttet /// og den administrerede ressource er blevet frigivet /// </summary> public void Udført () { lock ( this ) { if ( _runningThread != Thread . CurrentThread ) throw new ThreadStateException ( @"Wrong Thread" ); Int32 waitCount = _waiting . tælle ; if ( waitCount <= 0 ) { _runningThread = null ; } else if ( waitCount == 1 ) { _runningThread = _waiting . først (). nøgle ; _venter . Fjern ( _runningThread ); _begivenhed . sæt (); } andet { var næste = _waiting . først (); foreach ( var wait in _waiting ) { if ( wait . Value . ScheduleBefore ( next . Value )) { next = wait ; } } _runningThread = næste . nøgle ; _begivenhed . sæt (); } } } } /// <resumé> /// Hjælperklasse /// </summary> statisk delklasse ConvertTo { /// < summary> /// Hent det første element i samlingen /// </summary> /// < param name= "collection"></param> /// <returns></returns> public static KeyValuePair < Thread , ISchedulerOrdering > First ( denne ordbog < Thread , ISchedulerOrdering > samling ) { foreach ( var item in collection ) { returnere vare ; } smid ny ArgumentException (); } } }


bruger System ; navneområde Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Hvis flere operationer venter på at få adgang til en ressource, bruger <see cref="Scheduler"/>-klassen /// denne grænseflade til at bestemme rækkefølgen, hvori operationer skal udføres. /// </summary> interface ISchedulerOrdering { Boolean ScheduleBefore ( ISchedulerOrdering s ); } }


bruger System ; ved hjælp af System.Threading ; navneområde Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Eksempel på <see cref="JournalEntry"/> klassekode, der skal /// udskrives af <see cref="Printer"/> /// < /summary > class JournalEntry : ISchedulerOrdering { private static DateTime mTime = DateTime . nu ; privat DatoTid _tid ; /// <summary> /// Returnerer oprettelsestidspunktet for dette objekt /// </summary> public DateTime Time { get { return _time ; } } privat String_msg ; _ public JournalEntry ( String msg ) { mTime = mTime . AddSeconds ( 1 ); _tid = mTid ; _msg = besked ; } public void Do ( Int32 id ) { Console . WriteLine ( String . Format ( @"{0}: Begynd at gøre : {1} : {2}" , id , _time , _msg )); tråd . Søvn ( 1000 ); Konsol . WriteLine ( String . Format ( @"{0}: Afslut do : {1} : {2}" , id , _time , _msg )); } /// <resumé> /// Returnerer sand, hvis denne anmodning /// skal behandles før denne anmodning. /// </summary> /// <param name="s"></param> /// <returns></returns> public Boolean ScheduleBefore ( ISchedulerOrdering s ) { if ( s is JournalEntry ) { var otherJournalEntry = ( Journalentry ) s ; return ( dette . Time < otherJournalEntry . Time ); } returner falsk ; } } }


bruger System ; ved hjælp af System.Threading ; navneområde Digital_Patterns.Concurrency.Sheduler { public class Eksempel01 { private Printer _printer ; public void Kør () { Konsol . WriteLine ( @"Tryk på en vilkårlig tast for at starte, og tryk igen for at afslutte" ); Konsol . ReadKey (); _printer = ny printer (); ny tråd ( Tråd1 ). Start (); ny tråd ( Tråd2 ). Start (); ny tråd ( tråd3 ). Start (); Konsol . ReadKey (); } private void Thread1 () { var msg1 = new JournalEntry ( @"Køb vejafgift 5,45 USD" ); var msg2 = new JournalEntry ( @"Køb slik 1,05 USD" ); var msg3 = new JournalEntry ( @"Køb chokolade 3,25 USD" ); _printer . Udskriv ( msg1 ); _printer . Udskriv ( msg2 ); _printer . Udskriv ( msg3 ); } private void Thread2 () { var msg4 = new JournalEntry ( @"Køb postkort 2,05 USD" ); var msg5 = new JournalEntry ( @"Køb gerland 37,78 USD" ); _printer . Udskriv ( msg4 ); _printer . Udskriv ( msg5 ); } private void Thread3 () { var msg6 = new JournalEntry ( @"Køb bold 30,06 USD" ); var msg7 = new JournalEntry ( @"Køb rør 1,83 USD" ); _printer . Udskriv ( msg6 ); _printer . Udskriv ( msg7 ); } } }


bruger System ; ved hjælp af Digital_Patterns.Concurrency.Sheduler ; navneområde Digital_Patterns { class Program { static void Main ( string [] args ) { new Example01 (). køre (); Konsol . WriteLine ( @"Tryk på en vilkårlig tast for at afslutte" ); Konsol . ReadKey (); } } }

Links

  • Mark grand. Mønstre i Java bind 1: Et katalog over genanvendelige designmønstre illustreret med UML. - Wiley & Sons, 1998. - 480 s. — ISBN 0471258393 . (se synopsis  (engelsk) )