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 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
- Useat säikeet voivat käyttää resurssia samanaikaisesti, ja vain yksi säie kerrallaan voi käyttää resurssia.
- Ohjelman vaatimusten mukaisesti säikeiden on käytettävä resurssia tietyssä järjestyksessä.
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) )