2017-03-03 1 views
0

Ich schreibe eine Anwendung, in der der Haupt-Thread viele Verbindungen durch die Verwendung von Selector und SelectionKeys behandelt. Ich habe Probleme mit einer Race Condition bekommen, als ich versuchte, Aufgaben an die Worker Threads weiterzuleiten.Delegieren zu einem Thread-Pool mit einem Selektor und SelectionKeys

Meine Hauptschleife sieht wie folgt aus:

selector = Selector.open(); //Create selector 

    serverSocketChannel = ServerSocketChannel.open(); //Create socket channel, configure blocking, and bind 
    serverSocketChannel.configureBlocking(false); 
    serverSocketChannel.bind(new InetSocketAddress(PORT)); 

    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //Register channel to selector 

    ByteBuffer buffer = ByteBuffer.allocate(8000); 

    while(true){ 
     selector.select(); 

     Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); 

     while(iterator.hasNext()){ 
      SelectionKey key = iterator.next(); 

      if(key.isAcceptable()){ 
       SocketChannel socketChannel = serverSocketChannel.accept(); 
       socketChannel.configureBlocking(false); 
       socketChannel.register(selector, SelectionKey.OP_READ); 
      } 
      if(key.isReadable()){ 
       taskList.add(new ReadTask(key)); 
      } 
      if(key.isWritable()){ 

      } 

      iterator.remove(); 
     } 
    } 

Die Idee dabei ist, dass, wenn ein Client versucht, Daten an den Server zu senden, es einen Schlüssel mit OP_READ Interesse erhält und erstellt dann eine neue Aufgabe mit diesem Schlüssel so dass der Threadpool den Lesevorgang verarbeiten kann, um den Hauptthread nicht zu blockieren.

Das Problem ist, dass diese Schleife des Schlüssels während des Prozesses weiter Aufruf an einen Arbeiter-Thread weitergeleitet wird, und die gesamte Zeit zwischen dem taskList.add(new ReadTask(key)); genannt wird und die eventuelle key.channel().read(buffer) aufgerufen wird, wird der Haupt-Thread noch Iterieren und sieht die Schlüssel als noch ausgewählt wird. Nachdem der Schlüssel des Schlüssels gelesen wurde, wird der Schlüssel als inaktiv markiert und scheint nicht durch den Selektor ausgewählt zu werden, bis ein anderer legitimer Schreibvorgang von einem der Clients die erneute Aktivierung des Schlüssels fordert.

Gibt es eine Möglichkeit für mich, den Schlüssel zu markieren, damit er nicht durch den Selektor zurück zur Liste der ausgewählten Schlüssel hinzugefügt wird, ohne dass er gelesen wird? Ich habe versucht selector.selectedKeys.remove(key), aber dies ergibt eine ConcurrentModification Ausnahme.

Antwort

0

Sie sollten entweder den Lesevorgang in der Auswahlschleife ausführen und dann den Worker starten, um die Daten zu verarbeiten und die Antwort vorzubereiten, oder OP_READ aus interestOps des Auswahlschlüssels entfernen, bis die Antwort gesendet wurde.

+0

Die Worker-Threads sind bereits gestartet, diese Aufgaben werden über eine synchronisierte Warteschlange übergeben. Was Sie empfehlen ist, dass ich OP_READ zu einem anderen OP (wie OP_WRITE?), Bis der Lesevorgang aufgetreten ist? – 0x6

Verwandte Themen