Aikataulu (suunnittelukuvio)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 28.5.2019 tarkistetusta versiosta . tarkastukset vaativat 4 muokkausta .
Ajastin
Ajastin
Kuvattu suunnittelukuvioissa Ei

Ajastin on rinnakkainen  suunnittelumalli , joka tarjoaa mekanismin ajoituskäytännön toteuttamiseen, mutta joka ei ole riippuvainen tietystä käytännöstä. Ohjaa järjestystä, jossa säikeiden tulee suorittaa peräkkäinen koodi käyttämällä objektia, joka määrittää nimenomaisesti odottavien säikeiden järjestyksen.

Motiivit

Toteutusesimerkki

C# esimerkki

käyttäen System ; nimitila Digital_Patterns.Concurrency.Sheduler { luokka Tulostin { yksityinen staattinen Int32 mID = 0 ; yksityinen Scheduler _scheduler = uusi ajoitus (); public void Tulosta ( JournalEntry journalEntry ) { Int32 id = ++ mID ; kokeile { Konsoli . WriteLine ( String . Muoto ( @"{0}: syötä ajoitus" , id )); // kutsua ei suoriteta ennen kuin Scheduler-objekti // päättää, että on aika tulostaa tämä JournalEntry _scheduler -objekti . Enter ( journalEntry ); konsoli . WriteLine ( String . Muoto ( @"{0}: aloita tulostus" , id )); kokeile { //TODO Something JournalEntry . Tee ( id ); } lopuksi { // Done-metodin kutsuminen kertoo Schedulerille, että // JournalEntry-objekti on tulostettu ja toinen // JournalEntry _scheduler -objekti saattaa olla printin vieressä . Valmis (); konsoli . WriteLine ( String . Muoto ( @"{0}: valmis aikataulu" , id )); } } saalis ( poikkeus ) {} } } }


käyttäen System ; käyttäen System.Collections.Generic ; käyttäen System.Threading ; nimiavaruus Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Tämän roolin luokkaesiintymät hallitsevat Request-objektien käsittelyä <katso cref="JournalEntry"/> /// prosessoriobjektin suorittamaa <katso cref="Printer "/> . Ollakseen riippumaton /// pyyntötyypeistä, luokan <see cref="Scheduler"/> ei tarvitse tietää mitään hallitsemastaan ​​Request-luokasta. /// Sen sijaan se käyttää Request-objekteja niiden toteuttaman käyttöliittymän kautta <katso cref="ISchedulerOrdering"/> /// </summary> class Scheduler { /// <summary> /// Säikeen synkronointiobjekti /// < / yhteenveto> yksityinen AutoResetEvent _event = uusi AutoResetEvent ( false ); /// <yhteenveto> /// Aseta arvoksi nolla, jos ajastimen hallitsema resurssi on käyttämättömänä. /// </summary> yksityinen säie _runningThread ; /// <summary> /// Säikeet ja niiden pyynnöt odottavat /// </summary> yksityinen sanakirja < Thread , ISchedulerOrdering > _waiting = new Dictionary < Thread , ISchedulerOrdering >(); /// <summary> /// Metodi <see cref="Enter"/> kutsutaan ennen kuin säie alkaa käyttää hallittua resurssia. /// Metodia ei suoriteta ennen kuin hallittu resurssi vapautetaan ja <see cref="Sheduler"/>-objekti /// päättää, että tämän pyynnön suoritusjono on saapunut /// </summary> /// <param name ="s"></param> public void Enter ( ISchedulerOrdering s ) { var thisThread = Säie . CurrentThread ; lock ( this ) { // Selvitä, onko ajastin varattu if ( _runningThread == null ) { // Aloita saapuvan pyynnön suorittaminen välittömästi _runningThread = thisThread ; paluu ; } _odottaa . Lisää ( thisThread , s ); } lock ( thisThread ) { // Estä säiettä, kunnes ajoittaja päättää tehdä siitä nykyisen säikeen, kun taas ( thisThread != _runningThread ) { _event . odottaja (); _tapahtuma . asettaa (); // anna muiden säikeiden tarkistaa tilansa Thread . nukkua ( 1 ); } _tapahtuma . nollaa (); } lukko ( tämä ) { _odottaa . Poista ( thisThread ); } } /// <summary> /// Metodin <see cref="Done"/> kutsuminen osoittaa, että nykyinen säie on päättynyt /// ja hallittu resurssi on vapautettu /// </summary> public void Valmis () { lock ( this ) { if ( _runningThread != Thread . CurrentThread ) throw new ThreadStateException ( @"Wrong Thread" ); Int32 waitCount = _waiting . laskea ; if ( odotaLaskuri <= 0 ) { _runningThread = null ; } else if ( waitCount == 1 ) { _runningThread = _waiting . ensin (). avain ; _ odottaa . Poista ( _runningThread ); _tapahtuma . asettaa (); } else { var next = _waiting . ensimmäinen (); foreach ( var odottaa in _waiting ) { if ( odota . Arvo . AikatauluEnnen ( seuraava . Arvo )) { seuraava = odota ; } } _runningThread = seuraava . avain ; _tapahtuma . asettaa (); } } } } /// <summary> /// Apuluokka /// </summary> staattinen osaluokka ConvertTo { /// <summary> /// Hae kokoelman ensimmäinen elementti /// </summary> /// < param name= "collection"></param> /// <returns></returns> public static KeyValuePair < Thread , ISchedulerOrdering > Ensimmäinen ( tämä sanakirja < Thread , ISchedulerOrdering > collection ) { foreach ( var item in collection ) { palauta tuote ; } heittää uusi ArgumentException (); } } }


käyttäen System ; nimiavaruus Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Jos useat toiminnot odottavat pääsyä resurssiin, luokka <see cref="Scheduler"/> /// käyttää tätä käyttöliittymää määrittääkseen järjestyksen, jossa operaatioita tulee suorittaa. /// </summary> käyttöliittymä ISchedulerOrdering { Boolean ScheduleBefore ( ISchedulerOrdering s ); } }


käyttäen System ; käyttäen System.Threading ; nimiavaruus Digital_Patterns.Concurrency.Sheduler { /// <summary> /// Esimerkki <katso cref="JournalEntry"/> luokkakoodista, joka /// tulostetaan <katso cref="Printer"/> /// < /summary > class JournalEntry : ISchedulerOrdering { private static DateTime mTime = DateTime . nyt ; yksityinen DateTime _time ; /// <summary> /// Palauttaa tämän objektin luomisajan /// </summary> public DateTime Time { get { return _time ; } } yksityinen merkkijono_msg ; _ public JournalEntry ( String msg ) { mTime = mTime . AddSeconds ( 1 ); _aika = mTime ; _msg = msg ; } public void Do ( Int32 id ) { Konsoli . WriteLine ( String . Format ( @"{0}: Aloita tekemällä : {1} : {2}" , id , _time , _msg )); lanka . uni ( 1000 ); konsoli . WriteLine ( String . Format ( @"{0}: Finish do : {1} : {2}" , id , _time , _msg )); } /// <summary> /// Palauttaa tosi, jos tämä pyyntö /// pitäisi käsitellä ennen tätä pyyntöä. /// </summary> /// <param name="s"></param> /// <returns></returns> public Boolean ScheduleBefore ( ISchedulerOrdering s ) { if ( s is JournalEntry ) { var otherJournalEntry = ( JournalEntry ) s ; return ( this . Time < otherJournalEntry . Time ); } return false ; } } }


käyttäen System ; käyttäen System.Threading ; nimiavaruus Digital_Patterns.Concurrency.Sheduler { public class Esimerkki01 { yksityinen tulostin _tulostin ; public void Suorita () { Konsoli . WriteLine ( @"Paina mitä tahansa näppäintä aloittaaksesi ja paina uudelleen lopettaaksesi" ); konsoli . ReadKey (); _printer = uusi tulostin (); uusi säie ( Thread1 ). Aloita (); uusi säie ( Thread2 ). Aloita (); uusi säie ( Thread3 ). Aloita (); konsoli . ReadKey (); } private void Thread1 () { var msg1 = new JournalEntry ( @"Osta tiemaksu 5,45 USD" ); var msg2 = uusi JournalEntry ( @"Osta karkkia 1,05 USD" ); var msg3 = uusi JournalEntry ( @"Osta suklaata 3,25 USD" ); _tulostin . Tulosta ( msg1 ); _tulostin . Tulosta ( msg2 ); _tulostin . Tulosta ( msg3 ); } private void Thread2 () { var msg4 = new JournalEntry ( @"Osta postikortti 2,05 USD" ); var msg5 = uusi JournalEntry ( @"Osta gerland 37,78 USD" ); _tulostin . Tulosta ( msg4 ); _tulostin . Tulosta ( msg5 ); } private void Thread3 () { var msg6 = new JournalEntry ( @"Osta pallo 30,06 USD" ); var msg7 = uusi JournalEntry ( @"Osta putki 1,83 USD" ); _tulostin . Tulosta ( msg6 ); _tulostin . Tulosta ( msg7 ); } } }


käyttäen System ; käyttäen Digital_Patterns.Concurrency.Sheduler ; nimitila Digital_Patterns { class Program { static void Main ( merkkijono [] args ) { new Esimerkki01 (). juosta (); konsoli . WriteLine ( @"Paina mitä tahansa näppäintä lopettaaksesi" ); konsoli . ReadKey (); } } }

Linkit

  • Mark grand. Patterns in Java Volume 1: UML:lla kuvitettu uudelleenkäytettävien suunnittelumallien luettelo. - Wiley & Sons, 1998. - 480 s. — ISBN 0471258393 . (katso synopsis  (englanniksi) )