Se si invia sempre l'esecuzione a un pool di thread dopo select() return, si potrebbe desiderare di annullare immediatamente la chiave, poiché si perde il controllo nel tempo in cui Runnable verrà eseguito.
Es .: Se si esegue la selezione successiva() prima di annullare la chiave precedente (il thread è ancora in attesa di esecuzione), sarà ancora valida, causando un altro thread per trasportare la chiave già inviata. Se uno di questi thread annulla la chiave, l'altro otterrà un valore CancelledKeyException oltre a introdurre un comportamento imprevisto.
Anche se si annulla la chiave, un thread potrebbe registrare lo stesso canale (tasti di selezione degli aggiornamenti) prima che il canale venga annullato (a causa del precedente key.cancel()
). Che cosa, ancora, causerà un CancelledKeyException.
per sbarazzarsi di questa trappola, si può decidere di gestire gli eventi sempre nel ciclo successivo:
while (true) { // true or something less risky
//for each pendingTasks call
pool.execute(task);
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
key.cancel();
//store dispatch for the next while iteration
pendingTasks.add(task); // do not execute tasks before next select()
}
selector.select(TIMEOUT); // or selectNow if there are
//any pending events to handle.
}
esecuzione Firt sarà, quasi, non tornare mai più le chiavi, ma la select() alla fine del tuo loop MAGGIO garantisce che il canale della chiave cancellata non sia registrato (portalo fino al tuo impl) dal selettore.
Tuttavia, se si esegue semplicemente un'attività nello stesso thread si ascoltano gli eventi del selettore, l'aggiornamento dei suoni è facile e sicuro.
si cambierà il limite del selettore se nel pool di thread sono ancora in esecuzione attività.Se si utilizza un grande timout nel select(), è possibile causare thread bloccati per la registrazione di canali nuovi/esistenti sul selettore. – paulosuzart