Ho cercato di capire la necessità di implementare i thread utilizzando wait()
e notify()
quando si accede alle risorse condivise o si fa affidamento sul loro stato.Comprensione della necessità di attesa() e notifica()
Vedo che l'idea è di monitorare gli oggetti e di attendere la loro disponibilità e rilasciarli dopo l'uso per renderli utilizzabili per altri thread/metodi, ma perché sono quei metodi necessari invece di dichiarare gli oggetti rilevanti come statico volatile in modo che altri thread apprendano il cambiamento di stato senza richiamare quei metodi?
Per esempio
In un ristorante, ci sono 2 cuochi. Uno degli chef è un bravo chef (qualità di cucina migliore, ..) e porta un booleano isGoodCook = true
, mentre il secondo chef è un cattivo cuoco e porta un booleano isGoodCook = false
.
C'è solo l'attrezzatura per uno chef per cucinare i pasti alla volta. Il cattivo cuoco cucina per un periodo di tempo specifico (= tempo di cottura), mentre il bravo cuoco entra in cucina ogni tanto per assumere il compito del cattivo chef di cucinare i pasti. Il buon cuoco non può mai essere interrotto nel suo processo di cottura e cucina per tutta la sua cucina. Tempo dopo che ha iniziato.
(Lo chef cattivo smette di cucinare finché il bravo chef prende la parte dei pasti di cucina (= tempo di cucina del buon cuoco)).
E dopo che il bravo chef ha smesso di cucinare, il cattivo chef deve continuare il compito di preparare i pasti ancora una volta.
private boolean cooking; //is equipment used at the moment
private boolean isGoodCook;
private boolean cookingDesire; //indicating to chef to stop cooking
private int cookingTime;
public CookingTask(boolean isGoodCook, int cookingTime)
{
this.isGoodCook = isGoodCook;
this.cookingTime = cookingTime;
}
public void run()
{
if(isGoodCook)
{
//notify actual cook to stop cooking
cookingDesire = true;
}
//wait til equipment to cook
//is available
while(cooking)
{
try
{
wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
//reserve equipment
cooking = true;
cookingDesire = false;
//notify other threads (= bad cook)
notifyAll();
startCooking();
}
private void startCooking()
{
for(int i = 0; i < cookingTime; cookingTime--)
{
try
{
Thread.sleep(1000);
//if good chef comes in
if(cookingDesire)
{
//bad chef starts to pause
startBreak();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
cooking = false;
}
public void startBreak()
{
//bad chef stops cooking
cooking = false;
notifyAll();
//measure break time of bad chef
long stopCookingTime = System.currentTimeMillis();
while(cookingTime > 0 && cooking)
{
try
{
wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
int pausedTime = toIntExact((System.currentTimeMillis() - stopCookingTime)/1000);
//calculate remaining cookingTime
cookingTime -= pausedTime;
cooking = true;
notifyAll();
}
Forse qualcuno ha il tempo di leggere e poco delineare le mie idee sbagliate sul monitoraggio/wait()
e notify()
su più thread, mi piacerebbe molto grato!
perché è possibile contrassegnare un tipo di valore volatile o _reference_ su un oggetto, non sull'oggetto stesso –
Ciò ha senso e chiarisce le cose. Molte grazie! – freeprogramer233
La parola chiave volatile fornisce una forma debole di sicurezza del thread. Garantisce visibilità per i tipi di dati a 4 byte (e più brevi), ma non fornisce alcuna forma di mutua esclusione o atomicità. Quando è necessario il pieno controllo della sincronizzazione, wait() e notify() sono le strutture di basso livello che lo abilitano. La maggior parte dei programmatori Java non utilizza wait() o notify() e utilizza le API di concorrenza simultanee, più robuste e più semplici da utilizzare. – scottb