thread termino sincronizacion saber resueltos programacion multihilos hilos fuente entre ejercicios ejemplos diferencia concurrente componentes como codigo java multithreading sockets nio

termino - multihilos java



Java: ¿Ejemplos completos de código de bloqueo de hilos por conexión IO contra NIO? (3)

Ok, me estoy volviendo loco aquí. He estado reescribiendo el código de NIO para mi servidor y me he encontrado con dolores de cabeza. La conclusión es que conseguir NIO "a la derecha" es muy difícil. Algunas personas me indicaron el tutorial de Rox en http://rox-xmlrpc.sourceforge.net/niotut/ , que parece estar en buen camino, pero no es tan completo como me gustaría. Por ejemplo, necesito saber cómo cerrar una conexión en el servidor solo después de que se hayan enviado los ByteBuffers salientes en cola. SocketChannel.close () es abrupto y puede perder datos si se hace prematuramente. También necesito enviar paquetes grandes que son más grandes que el ByteBuffer leído. El código Rox (ni ningún otro código que haya analizado) se ocupa de esto. También hay muchos lugares donde parece que las excepciones no detectadas no se manejan adecuadamente. En mis pruebas, hay algunos errores y no está claro cómo manejarlos adecuadamente dada la complejidad de NIO.

De todos modos, cuando trato de resolver estos problemas, aparecen más sutilezas difíciles y se vuelve bastante complejo. Así que estoy considerando un enfoque completamente diferente. Muchas personas dicen que NIO es altamente propenso a errores y innecesariamente confuso y complejo. Abogan por utilizar un modelo de "hilo por conexión" que utiliza bloqueo IO donde cada conexión de socket se ejecuta en su propio hilo. Esto parece una buena idea, y reduciría el cuello de botella en el extremo frontal al tener un hilo de selector para todas las conexiones (como en NIO), a expensas de una mayor sobrecarga (para los hilos). Este sentimiento se refleja en publicaciones como http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html y http://mailinator.blogspot.com/2008/02/kill-myth- please-nio-is-not-faster-than.html

El código debería ser simple en comparación con NIO, pero realmente quiero ver un código de ejemplo. Parece que no puedo encontrar nada. El problema es que no creo que esta estrategia de "E / S de bloqueo de hilos por conexión" tenga un mejor nombre del que puedo obtener buenos resultados de Google. ¿Alguien puede vincularme con algunos tutoriales o ejemplos simples para explicar el uso de este método "antiguo" de E / S y escalarlo utilizando un grupo de subprocesos? ¿O tiene alguna otra palabra de sabiduría? ¡Muchas gracias!


Le sugiero que busque en el directorio sample / nio en su JDK. Esto tiene una cantidad de ejemplos simples que incluyen los dos que mencionas.


También puede considerar el uso de un marco de nivel superior como Grizzly en lugar de usar NIO directamente. El marco debería permitirle concentrarse en su caso de uso en lugar de las sutilezas de NIO.


Si está trabajando con NIO, también le sugiero usar un Framework. He estado trabajando con Apache Mina y lo recomendaría.

En cuanto al IO de bloqueo, esencialmente necesitará un hilo de escucha que acepte conexiones entrantes y engendre hilos adicionales que manejarán cada conexión. Aquí hay un ejemplo de dicho código de Escucha, como originalmente contribuyó al Proyecto Apache Felix. Si busca la versión completa pero modificada, puede buscar la fuente aquí .

p.ej

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.felix.shell.remote; import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; /** * Implements a simple listener that will accept a single connection. * <p/> * * @author Dieter Wimberger (wimpi) */ class Listener { private int m_Port; private Thread m_ListenerThread; private boolean m_Stop = false; private ServerSocket m_ServerSocket; private AtomicInteger m_UseCounter; private int m_MaxConnections; /** * Activates this listener on a listener thread (telnetconsole.Listener). */ public void activate() { //configure from system property try { m_Port = Integer.parseInt( System.getProperty( "osgi.shell.telnet.port", "6666" ) ); } catch ( NumberFormatException ex ) { Activator.getServices().error( "Listener::activate()", ex ); } try { m_MaxConnections = Integer.parseInt( System.getProperty( "osgi.shell.telnet.maxconn", "2" ) ); } catch ( NumberFormatException ex ) { Activator.getServices().error( "Listener::activate()", ex ); } m_UseCounter = new AtomicInteger( 0 ); m_ListenerThread = new Thread( new Acceptor(), "telnetconsole.Listener" ); m_ListenerThread.start(); }//activate /** * Deactivates this listener. * <p/> * The listener''s socket will be closed, which should cause an interrupt in the * listener thread and allow for it to return. The calling thread joins the listener * thread until it returns (to ensure a clean stop). */ public void deactivate() { try { m_Stop = true; //wait for the listener thread m_ServerSocket.close(); m_ListenerThread.join(); } catch ( Exception ex ) { Activator.getServices().error( "Listener::deactivate()", ex ); } }//deactivate /** * Class that implements the listener''s accept logic as a <tt>Runnable</tt>. */ private class Acceptor implements Runnable { /** * Listens constantly to a server socket and handles incoming connections. * One connection will be accepted and routed into the shell, all others will * be notified and closed. * <p/> * The mechanism that should allow the thread to unblock from the ServerSocket.accept() call * is currently closing the ServerSocket from another thread. When the stop flag is set, * this should cause the thread to return and stop. */ public void run() { try { /* A server socket is opened with a connectivity queue of a size specified in int floodProtection. Concurrent login handling under normal circumstances should be handled properly, but denial of service attacks via massive parallel program logins should be prevented with this. */ m_ServerSocket = new ServerSocket( m_Port, 1 ); do { try { Socket s = m_ServerSocket.accept(); if ( m_UseCounter.get() >= m_MaxConnections ) { //reject with message PrintStream out = new PrintStream( s.getOutputStream() ); out.print( INUSE_MESSAGE ); out.flush(); //close out.close(); s.close(); } else { m_UseCounter.increment(); //run on the connection thread Thread connectionThread = new Thread( new Shell( s, m_UseCounter ) ); connectionThread.start(); } } catch ( SocketException ex ) { } } while ( !m_Stop ); } catch ( IOException e ) { Activator.getServices().error( "Listener.Acceptor::activate()", e ); } }//run }//inner class Acceptor private static final String INUSE_MESSAGE = "Connection refused./r/n" + "All possible connections are currently being used./r/n"; }//class Listener

Puedes encontrar otros ejemplos aquí y aquí .

Tenga en cuenta que la ventaja de NIO sobre el modelo de bloqueo entra en juego cuando tiene más carga. A partir de cierto punto, la cantidad de trabajo adicional para la creación de subprocesos, la administración y el cambio de contexto limitará el rendimiento de su sistema.