2010-05-21 10 views
5

utilizzando uno java.nio deve registrare l'interesse in operazioni tramite il SelectableChannel:NIO Best Practices - SelectableChannel e InterestOps

SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask) 

Registrazione interesse:

  • sovrascrivendo il SelectionKey esistente eseguendo SelectableChannel.register con nuove operazioni
  • VS. l'aggiornamento del SelectionKey esistente con key.interestOps (key.interestOps() | newOp)

interesse annullamento della registrazione:

  • SelectionKey.cancel e SelectableChannel.register con nuove Ops
  • VS. aggiornamento del SelectionKey esistente come sopra

Ci sono dei pro & cons?

Grazie

risposta

3

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.

+0

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

3

vorrei aggiornare le interestOps esistenti utilizzando l'o-operator come lei suggerisce. Sarei preoccupato per le selezioni mancanti se ho (temporaneamente) cancellato il tasto di selezione.

Inoltre, annullare + registrarsi sembra più complicato dell'aggiornamento.

A meno che non si disponga di un motivo logico sottostante per la registrazione con nuove operazioni, suggerirei di andare sempre con l'aggiornamento.

Problemi correlati