Ho una discussione che aggiorna il suo stato di tanto in tanto e voglio che un secondo thread sia in grado di aspettare che il primo thread sia fatto. Qualcosa di simile a questo:In attesa di un evento in Java: quanto è difficile?
Thread 1:
while(true) {
...do something...
foo.notifyAll()
...wait for some condition that might never happen...
...
}
Thread 2:
...
foo.wait();
...
Ora, questo sembra bello e tutto meno che Thread 1 di notifyAll() viene eseguito prima attesa Thread 2 di(), in cui Discussione caso 2 attende fino Discussione 1 Notifica nuovo (che potrebbe mai accadere) .
miei possibili soluzioni:
a) potrei usare un CountDownLatch o di un futuro, ma entrambi hanno il problema che essi intrinsecamente eseguito solo una volta . Cioè, nel thread while di Thread 1, avrei bisogno di creare un nuovo foo per aspettare ogni volta e Thread 2 avrebbe bisogno di chiedere quale foo aspettare. Ho una brutta sensazione semplicemente scrivendo
while(true) {
foo = new FutureTask();
...
foo.set(...);
...wait for a condition that might never be set...
...
}
come temo che a foo = new FutureTask(), cosa succede quando qualcuno attese che il vecchio foo (per "qualche ragione", impostato non è stato chiamato, ad esempio, un bug nella gestione delle eccezioni)?
b) Oppure potrei usare un semaforo:
class Event {
Semaphore sem;
Event() { sem = new Semaphore(1); sem . }
void signal() { sem.release(); }
void reset() { sem.acquire(1); }
void wait() { if (sem.tryAcquire(1)) { sem.release(); } }
}
ma temo che v'è una certa condizione di competizione, se più thread sono wait() ing per esso mentre un altro segnale() s e reset ()S.
Domanda:
non c'è nulla nelle API Java analogo al comportamento degli eventi di Windows? Oppure, se si disprezza Windows, qualcosa come GolG's WaitGroup (cioè un CountDownLatch che consente countUp())? Nulla?
Come fare manualmente:
Thread 2 non può semplicemente aspettare a causa della sveglia spuria e in Java non c'è modo di sapere il motivo per cui Object.wait() ha restituito. Quindi ho bisogno di una variabile di condizione che memorizzi se l'evento è segnalato o meno. Thread 2:
synchronized(foo) {
while(!condition) {
foo.wait();
}
}
E Thread 1 ovviamente imposta condizione su true in un blocco sincronizzato. Grazie a weekens per il suggerimento!
Esiste una classe esistente che include questo comportamento?
Oppure devo copiare e incollare il codice dappertutto?
quale problema si è in realtà cercando di risolvere? Anche se sono sicuro che questo problema possa essere risolto, vorrei comunque chiederlo perché sappiamo che questa è la soluzione giusta per il tuo problema. Questo tipo di intrighi con discussioni e semafori, ben inteso, è soggetto a fallimenti a causa di piccoli errori, quindi potrebbe esserci un modo più leggibile e facile da capire per fare ciò che si vuole ottenere. In particolare suona come un semplice schema di evenlistener in cui gli ascoltatori registrati con la fonte degli eventi sarebbero più adatti. – Thor84no
Sì, un listener di eventi risolverebbe il problema lasciando passare gli aggiornamenti "push" del thread 1. Questo è solitamente il metodo preferito, ad es. in un ambiente server. Tuttavia, mi sono imbattuto nel problema di thread-safe "tirando" gli aggiornamenti di volta in volta e non ho mai avuto una soluzione pulita fino ad ora. – Kosta