Domanda
Si prega di indicare / me fornisce un esempio di lavoro di metodo selector.wakeup();
tra due thread.
Ho cercato di creare un semplice programma in cui un filo è in attesa di metodo selector.select (). Secondo filo crea alcuni prese e tenta di registrare con il selettore; in cui il primo filo è bloccato.
Quindi devo usare il metodo wakeup
del selettore, ma in qualche modo il primo depliant filo non esce dalla modalità di blocco.
Il Javadoc del metodo di risveglio afferma:
Se un altro filo è attualmente bloccato in un'invocazione del Selector.select () o Selector.select metodi (a lungo) e poi che invocazione tornerà immediatamente.
P.S Ci sono pochi altri work-around; uno di loro è select (timeout), ma sto cercando di capire dove l'errore è.
La pseudo-codice:
primo filo:
static Selector selector = Selector.open();
while(true) {
int n = selectorGlobal.select();
selectorKeySet = selectorGlobal.selectedKeys().iterator();
while (selectorKeySet.hasNext()) {
selectionKey = selectorKeySet.next();
if (selectionKey.isReadable()) {
//do something
}
if(selectionKey.isAcceptable()) {
//accept
}
}
}
secondo filo:
while (itr.hasNext()) {
data = (String) itr.next();
String IP = data.get(0);
String Port = data.get(1);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
boolean isConnected = socketChannel.connect(new InetSocketAddress(IP, Port));
ClassName.selector.wakeup();
SelectionKey selectionKey = SelectSockets.registerChannel(ClassName.selector,
socketChannel, SelectionKey.OP_READ);
}
Soluzione
Probabilmente non si vuole avere la presa a partire da fili 2 ostruire se si sta registrando in un selettore (come selettori sono pensati per non-blocking I / O). Penso che sia anche pratica comune per far gestire il selettore del collegamento con OP_CONNECT (utilizzando SocketChannel.finishConnection ()).
Sembra inoltre che si potrebbe avere un potenziale condizione di gara qui. Immaginate questa serie di eventi:
- filettatura 1: selector.select ()
- ... il tempo passa ...
- filettatura 2: Thread1.selector.wakeup ()
- filettatura 1: chiavi verifica la presenza di accettabilità
- filettatura 1: chiavi verifica la presenza di leggibilità
- filettatura 1: ciclo
- filettatura 1: selector.select ()
- Discussione 2: provare a registrare nel selettore (ma è troppo tardi per questo select ())
Io suggerirei di avere Thread 2 istituito un SocketChannel, riporre via da qualche parte Thread 1 può arrivare a esso (assicuratevi di essere thread-safe quando si esegue questa operazione), poi svegliarsi il selettore, lasciarlo controllare che sia chiavi esistenti nella Discussione 1 e hanno filettatura 1 registrare i nuovi SocketChannel prima di chiamare Selector.select () di nuovo.