2009-11-04 18 views
5

Proszę wskazać/dostarczyć mi działający przykład metody selector.wakeup(); między dwoma wątkami.java nio Wybieranie wybiórcze

Próbowałem utworzyć prosty program, w którym wątek czeka na metodę selektor.select(). Drugi wątek tworzy kilka gniazd i próbuje zarejestrować się przy pomocy selektora; na którym pierwszy wątek jest zablokowany.

Dlatego potrzebuję użyć metody selektora wakeup, ale jakoś pierwszy wątek nie wychodzi z trybu blokowania.

Javadoc stanów czuwania Metoda:

Jeśli inny gwint jest obecnie zablokowany w wezwaniem Selector.select() lub Selector.select (długimi) Methods następnie że wywołanie powróci natychmiast.

P. S Istnieje niewiele innych obejść; jeden z nich jest wybrany (timeout), ale próbuję ustalić, gdzie jest błąd.

psuedo-code:

pierwszy wątek:

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 
     } 
    } 
} 

drugi wątek:

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); 

} 

Odpowiedz

4

Prawdopodobnie nie chcą mieć gniazdo z nici 2 być blokowane, jeśli rejestrujesz go w selektorze (ponieważ selektory są przeznaczone do nie blokujących operacji we/wy). Myślę, że jest również powszechną praktyką, aby selektor obsługiwał połączenie za pomocą OP_CONNECT (używając SocketChannel.finishConnection()).

Wygląda na to, że możesz mieć tutaj potencjalną sytuację wyścigową. Wyobraź sobie tę serię wydarzeń:

  1. gwintu 1: selector.select()
  2. ... czas płynie ...
  3. gwintu 2: Thread1.selector.wakeup()
  4. gwintu 1: kontrole klucze akceptowalności
  5. gwintu 1: kontrole kluczy dla czytelności
  6. gwintu 1: pętla
  7. gwintu 1: selector.select()
  8. gwintu 2: próbować zarejestrować w selektorze (ale jest już za późno na to select())

Sugerowałbym mający gwintu 2 założyć SocketChannel, schować go gdzieś gwintu 1 puszka dostać się do niego (upewnij się, że robisz to bezpiecznie), a następnie obudź selektor, pozwól mu sprawdzić istniejące klucze w wątku 1, a wątek 1 zarejestruj nowy SocketChannel, zanim ponownie wywoła Selector.select().

+0

Dziękuję Seth.Łączenie z innymi gniazdami to działanie, które działo się bardzo rzadko; dlatego żałuję, że w jakiś sposób wątek selektora nie sprawdzałby jakiejś kolekcji/zmiennej za każdym razem, gdy jest czynność na klawiszach wyboru. – Nilesh