|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
"eventi" (di sincronizzazione) in Java
in un programma Java ho un certo numero di threads che devono bloccarsi in attesa che si verifichi un certo evento; questo evento dovrebbe essere provocato da un altro thread che subito dopo dovrebbe risvegliare tutti gli altri.
in altre parole dovrei realizzare in Java un meccanismo come gli eventi di Win32. stavo pensando di utilizzare come oggetto che rappresenta l'evento (stavolta inteso come meccanismo di sincronizzazione) un generico Object: i thread si bloccano con la wait e il thread che provoca l'evento li sblocca con notifyAll. è una cavolata o ha senso? un po' di pseudocodice: Codice:
private Object event;
.
.
.
<metodo chiamato dal thread che attende>
while (!<condizione che termina definitivamente l'attesa>) {
try {
event.wait();
}
catch (InterruptedException e) {
}
}
.
.
.
<metodo chiamato dal thread che provoca l'evento>
event.notifyAll();
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Dec 2002
Messaggi: 3359
|
Ciao, tempo fa aprii un thread simile, guarda se ti può tornare utile
http://www.hwupgrade.it/forum/showthread.php?t=1249755 |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
mmmm..
al java day di due sabati fa hanno postato un interessante esempiuccio ke utilizzava le variabili di tipo volatile per mantenere la coerenza tra + thread... spè ke ti trovo il codice Codice:
class MyThread extends Thread {
public void run() {
while (!done) { // fai qualcosa ... }
}
public void setDone() { done = true; }
private volatile boolean done;
}
__________________
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
dimenticavo..
le volatile non garantiscono l'atomicità... Per l'atomicità dovresti usare il tipo java.util.concurrency.Atomic o qualcosa del genere
__________________
|
|
|
|
|
|
#5 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
è, ho capito ma sti thread non devono mica spremere la CPU, si devono bloccare
MEMon, ho leggiucchiato il thread che mi hai linkato ma non riesco a capacitarmi: possibile che una cosa simile si debba implementare per forza con tutto quel codice? O_O io volevo una cosa semplice semplice, non ditemi che devo scrivermi la mia classe Event il mio codice funzica? ovviamente no, visto che non ho capito un cacchio dei monitor; perché non funzica? fatemi capire |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
e c'ha anke ragione direi
__________________
|
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Lo pseudo codice di 71104 non fa una piega. Probabilmente si tratta solo di un dettaglio mancante. Non ricordo il contesto del thread segnalato da Memon ma non è necessario ingrufolarsi in milione di linee per tradurre quello pseudocodice in Java.
Noterei come ci sia una corrispondenza praticamente diretta tra le intenzioni espresse e la forma in cui sono traducibili. Codice:
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.*;
public class Main {
private final Lock signalLock = new ReentrantLock();
private final Condition signalCondition = signalLock.newCondition();
public void waitForSignal() {
try {
signalLock.lock();
signalCondition.await();
} catch(InterruptedException ex) {
} finally {
signalLock.unlock();
}
}
public void signal() {
try {
signalLock.lock();
signalCondition.signalAll();
} finally {
signalLock.unlock();
}
}
public static void main(String[] args) {
final Main main = new Main();
Runnable stuntTask = new Runnable() {
public void run() {
main.waitForSignal(); //qui i thread si spantegano sulla barriera
System.out.println(Thread.currentThread().getName() + " free!!!!");
}
};
for(int i = 0; i < 10; i++) {
new Thread(stuntTask, "StuntThread n. " + i).start();
}
System.out.println("Press enter to release stuntthreads...");
Scanner in = new Scanner(System.in);
in.nextLine();
main.signal(); //e qui vengono aperte le porte
}
}
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
eh bhè..
questo mi sa ke funziona.. ma non stai usando wait e notifyAll stai usando i costrutti di java 5 il codice scritto da 71104 avrebbe lanciato un'eccezione xkè ank'io l'ho scritto un migliaio di volte masokisticamente senza imparare mai ![]() il wait e notifyAll danno quel problema perchè un monitor bloccato su un oggetto può essere sbloccato solo dall'owner del monitor (ke mi sa ke è l'oggetto stesso se non erro). Cmq non lo so spiegare bene dato ke ho le idee un pò confuse anch'io su wait e notify. Molto ma molto meglio utilizzare i costrutti ad alto livello forniti da java.util.concurrent
__________________
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Dec 2000
Città: bologna
Messaggi: 1309
|
volatile dalla 1.5 in funziona "in tutto e per tutto".
Codice:
volatile String pippo = "p";
public void asd()
{
a();
String c = pippo+"a";
b();
}
prima della 1.5 invece c'erano dei buchi...(letto tutto su un jsr) |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Questo perchè le specifiche del memory model di java erano troppo lacunose e davano adito a diverse interpretazioni, e soprattutto alcuni costrutti utilizzati per migliorare le performance della gestione dei thread dovevano x forza di cose "violare" le specifiche (se si può dire violare x una specifica non ben definita) Invece dalla versione 5 in poi è stata definita correttamente la relazione di Happens Before x il memory model e sono state aggiornate le specifiche in maniera congruente, cosikkè tutte le impliementazioni ke seguono le specifiche di java 5 non danno + alcun problema con il multi-threading (non che prima ne dessero x forza...ma diciamo che andava un pò a culo a seconda dell'implementazione
__________________
|
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
L'intuizione di Tigershark è corretta.
Il linguaggio stabilisce che l'invocazione di wait e notify deve avvenire in condizione di possesso esclusivo, parte del Thread che esegue l'invocazione, del monitor associato all'istanza che possiede i metodi wait o notify invocati. In Java tale possesso esclusivo è garantito nel caso in cui l'accesso avvenga all'interno di un blocco sincronizzato sull'oggetto a cui appartiene il metodo wait/notify invocato o all'interno di un metodo sinchronized nel caso in cui l'oggetto in questione sia "this". Cioè sincronizzi, sull'oggetto X, per escludere che qualche altro Thread possa mettere le mani sul monitor associato a X, mentre invochi wait o notify su X. Non fatico ad immaginare che dietro tale regola vi sia qualche necessità strutturale. Ma per quello che interessa a noi basta e avanza che sia la lingua ad imporlo. [AGGIUNTO] P.s.: mi riferivo al wait e al notify, non al volatile. |
|
|
|
|
|
#12 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
dunque per capirci ![]() se io volessi realizzare una mia classe Event in questa forma: Codice:
class Event
{
public void myWait() // può essere chiamato da qualsiasi thread in qualsiasi momento
{
...
}
public void myNotifyAll() // idem come sopra
{
...
}
}
vanno bene i metodi waitForSignal e signal dell'esempio di PGI-Bis? cioè devo usare come minimo due oggetti (un ReentrantLock e una Condition)? a me pare assurdo che una perla come Java abbia una tale carenza ![]() in Win32 è sufficiente aprire un solo HANDLE e si ha un meccanismo notevolmente versatile ![]() mah |
|
|
|
|
|
|
#13 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
a proposito, non è che tante volte in Java 6 c'è una bella classe EventEspeciallyMadeFor71104 già pronta?
![]() no perché io ho già 2 buoni motivi per passare a Java 6 (di cui uno addirittura ottimo), e questo non sarebbe altro che il terzo |
|
|
|
|
|
#14 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ah, dimenticavo: sempre facendo riferimento al confronto con Win32, l'esempio di PGI-Bis NON è "manual reset", giusto?
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
guarda se scritto ks ti piace di + Codice:
public class ProvaThread {
volatile boolean condition = false;
public ProvaThread() {
while(condition) {
//do something;
}
}
public void myNotify() {
condition = true;
}
public void myWait() {
condition=false;
}
}
__________________
|
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
mmmmm..
ora ho capito ke intendevi ![]() e mi sa ke il mio codice non va bene xkè comunque aspetta di finire quello ke sta facendo nel ciclo e non si ferma immediatamente boh.. dai un okkiata a java.util.concurrent e vedi se c'è qualco'altro ke fa al caso tuo
__________________
|
|
|
|
|
|
#17 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
e bhè? ke problema c'è? diamonds non ti ha insegnato niente? un bel Thread.sleep(1) dentro il while e il problema è risolto.. e se vedi ke succhia ancora cpu mettigli 2, 3 o quello ke ti pare
__________________
|
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Cosenza --> Roma
Messaggi: 853
|
che ne diti della comoda CyclicBarrier
presente in java 5.0
__________________
GNU MyServer Wants YOU!! We live thinking we will never die. We die thinking we had never lived. Jason Becker |
|
|
|
|
|
#20 | |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Codice:
public class Event {
private boolean wakeup;
public synchronized void myWait() {
try {
while(!wakeup) {
wait();
}
} catch(InterruptedException ex) {
return;
}
}
public synchronized void myNotifyAll() {
wakeup = true;
notifyAll();
}
}
|
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:42.











fatemi capire 











