Ütemező (tervezési minta)
Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2019. május 28-án felülvizsgált
verziótól ; az ellenőrzések 4 szerkesztést igényelnek .
Az ütemező egy párhuzamos tervezési minta , amely mechanizmust biztosít egy ütemezési házirend megvalósításához, de nem függ semmilyen konkrét házirendtől. Azt a sorrendet szabályozza, amelyben a szálak szekvenciális kódot hajtsanak végre egy olyan objektum használatával, amely kifejezetten meghatározza a várakozó szálak sorrendjét.
Motívumok
- Egyszerre több szál is hozzáférhet egy erőforráshoz , és egyszerre csak egy szál férhet hozzá egy erőforráshoz.
- A program követelményeivel összhangban a szálaknak meghatározott sorrendben kell hozzáférniük az erőforráshoz.
Megvalósítási példa
C# példa
a rendszer használatával ;
névtér Digital_Patterns.Concurrency.Sheduler
{
class Printer
{
private static Int32 mID = 0 ;
private Scheduler _scheduler = new Scheduler ();
public void Nyomtatás ( JournalEntry journalEntry )
{
Int32 id = ++ mID ;
próbálkozzon
{
Console . WriteLine ( String . Formátum ( @"{0}: írja be az ütemezőt" , id ));
// a hívás addig nem kerül végrehajtásra, amíg az Ütemező objektum
// úgy dönt, hogy ideje kinyomtatni ezt a JournalEntry
_scheduler objektumot . Enter ( JournalEntry );
Konzol . WriteLine ( String . Formátum ( @"{0}: nyomtatás indítása" , id ));
próbálkozzon
{
//TODO Something
journalEntry . Do ( id );
}
végül
{
// a Done metódus meghívása közli az ütemezővel, hogy // a JournalEntry objektum ki lett
nyomtatva, és egy másik
// JournalEntry
_scheduler objektum lehet a print mellett . Kész ();
Konzol . WriteLine ( String . Formátum ( @"{0}: kész ütemező" , id ));
}
}
fogás ( Kivétel ) {}
}
}
}
a rendszer használatával ;
a System.Collections.Generic használatával ;
a System.Threading használatával ;
névtér Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Ebben a szerepkörben az osztálypéldányok szabályozzák a Request objektumok feldolgozását <lásd cref="JournalEntry"/>
/// a Processor objektum által végrehajtott <lásd cref="Nyomtató" "/> . Ahhoz, hogy a /// kéréstípusoktól független legyen
, a <see cref="Scheduler"/> osztálynak semmit sem kell tudnia az általa kezelt Request osztályról.
/// Ehelyett az általuk megvalósított felületen keresztül éri el a Request objektumokat <see cref="ISchedulerOrdering"/>
/// </summary>
class Scheduler
{
/// <summary>
/// Szálszinkronizációs objektum
/// < / összegzés>
private AutoResetEvent _event = new AutoResetEvent ( false );
/// <összegzés>
/// Állítsa nullára, ha az ütemező által kezelt erőforrás tétlen.
/// </summary>
private Thread _runningThread ;
/// <summary>
/// Szálak és kéréseik várakoznak
/// </summary>
private Dictionary < Thread , ISchedulerOrdering > _waiting = new Dictionary < Thread , ISchedulerOrdering >();
/// <summary>
/// A <see cref="Enter"/> metódus meghívásra kerül, mielőtt a szál elkezdené használni a felügyelt erőforrást.
/// A metódus addig nem hajtódik végre, amíg a felügyelt erőforrás fel nem szabadul, és a <see cref="Sheduler"/> objektum
/// úgy dönt, hogy a kérés végrehajtási sora megérkezett
/// </summary>
/// <param name ="s"></param>
public void Enter ( ISchedulerOrdering s )
{
var thisThread = Szál . CurrentThread ;
lock ( this )
{
// Határozza meg, hogy az ütemező foglalt-
e if ( _runningThread == null )
{
// Azonnal kezdje el végrehajtani a bejövő kérést
_runningThread = thisThread ;
visszatérés ;
}
_vár . Add ( thisThread , s );
}
lock ( thisThread )
{
// Blokkolja a szálat mindaddig, amíg az ütemező úgy dönt, hogy az aktuális szál lesz
, miközben ( thisThread != _runningThread )
{
_event . várakozó ();
_esemény . set (); // hagyja, hogy a többi szál ellenőrizze állapotát
Thread . alvás ( 1 );
}
_esemény . visszaállítás ();
}
zár ( ez )
{
_vár . Eltávolítás ( thisThread );
}
}
/// <summary>
/// A <see cref="Done"/> metódus meghívása azt jelzi, hogy az aktuális szál leállt
/// és a felügyelt erőforrás felszabadult
/// </summary>
public void Kész ()
{
lock ( this )
{
if ( _runningThread != Thread . CurrentThread )
throw new ThreadStateException ( @"Wrong Thread" );
Int32 waitCount = _waiting . gróf ;
if ( várniSzám <= 0 )
{
_futószál = null ;
}
else if ( waitCount == 1 )
{
_runningThread = _waiting . először (). kulcs ;
_vár . Eltávolítás ( _runningThread );
_esemény . set ();
}
else
{
var next = _vár . első ();
foreach ( var wait in _waiting )
{
if ( várjon . Érték . Ütemezés előtt ( next . Value ))
{
next = vár ;
}
}
_runningThread = következő . kulcs ;
_esemény . set ();
}
}
}
}
/// <summary>
/// Segítő osztály
/// </summary>
statikus részleges osztály ConvertTo
{
/// <summary>
/// A gyűjtemény első elemének lekérése
/// </summary>
/// < param name= "collection"></param>
/// <returns></returns>
public static KeyValuePair < Thread , ISchedulerOrdering > Először ( ez a szótár < Thread , ISchedulerOrdering > collection )
{
foreach ( var item in collection )
{
cikk visszaküldése ; } dob új ArgumentException (); } }
}
a rendszer használatával ;
névtér Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Ha több művelet vár egy erőforrás elérésére, a <see cref="Scheduler"/> osztály
/// ezt a felületet használja annak meghatározására, hogy milyen sorrendben műveleteket kell végrehajtani.
/// </summary>
interface ISchedulerOrdering
{
Boolean ScheduleBefore ( ISchedulerOrdering s );
}
}
a rendszer használatával ;
a System.Threading használatával ;
névtér Digital_Patterns.Concurrency.Sheduler
{
/// <summary>
/// Minta <lásd a cref="JournalEntry"/> osztálykódot, amelyet
/// ki kell nyomtatnia <see cref="Printer"/>
/// < /summary >
class JournalEntry : ISchedulerOrdering
{
private static DateTime mTime = DateTime . most ;
privát DateTime _time ;
/// <summary>
/// Az objektum létrehozási idejét adja vissza
/// </summary>
public DateTime Time { get { return _time ; } }
privát karakterlánc_üzenet ; _
public JournalEntry ( String msg )
{
mTime = mTime . AddSeconds ( 1 );
_time = mTime ;
_msg = msg ;
}
public void Do ( Int32 id )
{
Konzol . WriteLine ( String . Formátum ( @"{0}: Kezdje el : {1} : {2}" , id , _time , _msg ));
szál . Alvás ( 1000 );
Konzol . WriteLine ( String . Formátum ( @"{0}: Befejezés do : {1} : {2}" , id , _time , _msg ));
}
/// <összefoglaló>
/// Igaz értéket ad vissza, ha ezt a kérést
/// a kérés előtt kell feldolgozni.
/// </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 ;
}
}
}
a rendszer használatával ;
a System.Threading használatával ;
névtér Digital_Patterns.Concurrency.Sheduler
{
public class Példa01
{
private Printer _printer ;
public void Futtatás ()
{
Konzol . WriteLine ( @"Nyomja meg bármelyik gombot az indításhoz, és nyomja meg újra a befejezéshez" );
Konzol . ReadKey ();
_printer = új nyomtató ();
új szál ( Thread1 ). Indítás ();
új szál ( Thread2 ). Indítás ();
új szál ( Thread3 ). Indítás ();
Konzol . ReadKey ();
}
private void Thread1 ()
{
var msg1 = new JournalEntry ( @"Újdíj vásárlása 5,45 USD" );
var msg2 = new JournalEntry ( @"cukorka vásárlása 1,05 USD" );
var msg3 = new JournalEntry ( @"Vegyél csokoládét 3,25 USD-ért" );
_printer . Nyomtatás ( msg1 );
_printer . Nyomtatás ( msg2 );
_printer . Nyomtatás ( msg3 );
}
private void Thread2 ()
{
var msg4 = new JournalEntry ( @"Levelezőlap vásárlása 2,05 USD" );
var msg5 = new JournalEntry ( @"Buy Gerland 37.78 USD" );
_printer . Nyomtatás ( msg4 );
_printer . Nyomtatás ( msg5 );
}
private void Thread3 ()
{
var msg6 = new JournalEntry ( @"Gyó vásárlás 30,06 USD" );
var msg7 = new JournalEntry ( @"Buy pipe 1,83 USD" );
_printer . Nyomtatás ( msg6 );
_printer . Nyomtatás ( msg7 );
}
}
}
a rendszer használatával ;
a Digital_Patterns.Concurrency.Sheduler használatával ;
névtér Digital_Patterns
{
class Program
{
static void Main ( string [] args )
{
new Példa01 (). futni ();
Konzol . WriteLine ( @"Nyomja meg bármelyik billentyűt a befejezéshez" );
Konzol . ReadKey ();
}
}
}
Linkek
- Mark grand. Minták a Java-ban 1. kötet: UML-lel illusztrált, újrafelhasználható tervezési minták katalógusa. - Wiley & Sons, 1998. - 480 p. — ISBN 0471258393 . (lásd az összefoglalót (angol) )