2010-05-17 11 views
8

Me pregunto si un típico while(true) ServerSocket escuchar bucle lleva un núcleo entero que esperar y aceptar una conexión de cliente (incluso cuando la aplicación ejecutable y el uso de Thread .start())Eficiencia de while (true) ServerSocket Escucha

Me estoy poniendo en práctica un tipo del clúster de computación distribuida y cada computadora necesita cada núcleo que tiene para el cálculo. Un nodo maestro necesita comunicarse con estas computadoras (invocando métodos estáticos que modifican el funcionamiento del algoritmo).

La razón por la que necesito utilizar sockets se debe a las capacidades de plataforma cruzada/lenguaje cruzado. En algunos casos, PHP invocará estos métodos estáticos de Java.

Utilicé un generador de perfiles de Java (YourKit) y puedo ver el hilo de ejecución de ServerSocket en ejecución y nunca duerme, y siempre se está ejecutando. ¿Hay un mejor enfoque para hacer lo que quiero? O, ¿el rendimiento será insignificante?

Por favor, siéntase libre de ofrecer cualquier sugerencia si se puede pensar en una mejor manera (He intentado RMI, pero no se admite entre lenguajes.

Gracias a todos

+1

Por lo tanto, no debería ocurrir si está utilizando 'aceptar'. ¿Puedes publicar algún código? – msandiford

+0

erickson estaba justo en el lugar con el código que publicó while (true) { Socket socket = server.accept(); /* Haga algo con el zócalo ... */ } – Submerged

+0

¿Cuántas conexiones/segundo está manejando? – msandiford

Respuesta

8

Si quiere decir algo como esto:

while (true) { 
    Socket socket = server.accept(); 
    /* Do something with socket... */ 
} 

entonces, no, la llamada a accept() no "toman un núcleo entero." Es una llamada de bloqueo que permitirá que la CPU se programe para otro hilo hasta que el cliente se conecte. Una vez que la llamada a accept() regrese, el hilo actual se programará para ejecutarse y consumirá la CPU hasta que se bloquee en accept() en la siguiente iteración del ciclo.

Para evitar el retraso en la escucha de otros clientes que crecen demasiado, otro subproceso suele manejar la interacción con el recién aceptado Socket, dejando un hilo para centrarse en aceptar nuevos clientes. El hilo de manejo de socket podría manejar muchos sockets, usando NIO, o podría estar dedicado a un único socket, que es mucho más simple de codificar pero no escalará mucho más allá de muchos cientos de conexiones simultáneas.

0

Deje que el núcleo dormir un poco. en el método de Ejecutable, añadir algo como

Thread.sleep(250); // milliseconds 

en cada bucle.

Eso debería reducir significativamente el uso de la CPU

Editar: mala idea, ver los comentarios, lo siento, es mi culpa


Y: no utilizar while (true). es un diseño horrible, ya que la semántica sugiere que finalmente la verdad ya no será cierta. Por lo general, tendrá que consultar alguna variable volátil o atómica desde el hilo principal

public class MyClass { 

class MyRunnable implements Runnable { 

    public void run() { 
     while (MyClass.this.keepGoing.get()) { 
      // listen(); 
      try { 
       Thread.sleep(500); 
      } catch (InterruptedException e) { 
       // deal with exception 
      } 

     } 
    } 

} 

private final AtomicBoolean keepGoing = new AtomicBoolean(true); 

} 

De esta manera el hilo principal tiene una manera de detener la hebra de escucha.

+3

No estoy seguro de que sea una buena idea, ya que limitará sus conexiones. – msandiford

+0

yup, leí mal la pregunta. Pensé que era solo un hilo que esperaba que se iniciara algún servicio, pero para un oyente de Socket que realmente escucha las solicitudes de los usuarios, este es un mal consejo. –

+0

hola, ¿en qué contexto quieres decir "verdad ya no será verdad"? – bragboy

5

Es posible que desee echar un vistazo a las bibliotecas Java 1.4 nio y en particular ServerSocketChannel.Yo uso este gran éxito para implementar un servidor eficiente, los bits de la clave de código son:

Selector selector = Selector.open(); 

ServerSocketChannel server= ServerSocketChannel.open(); 
server.socket().bind(new java.net.InetSocketAddress(port)); 
server.configureBlocking(false); 
SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT); 

// start listening thread 
new Thread(listener).start(); 

y el oyente es sólo un bucle que se ejecuta:

selector.select(1000); // listen for one second max 
Set<SelectionKey> keys = selector.selectedKeys(); 

if (keys.size()>0) { 
    handleKeys(keys); 
} 
+0

Estaba buscando canales socket, ¡gracias por publicar esto! – Submerged

3

utilicé un perfilador de Java (YourKit) y puedo ver mi hilo de escucha ServerSocket en ejecución y nunca duerme, y siempre se está ejecutando.

Básicamente, el generador de perfiles te está engañando.

que asuma que su código es el siguiente:

ServerSocket server = ... 
// configure server socket 

try { 
    while (true) { 
     Socket socket = server.accept(); 
     // do something with socket (and close it afterwards!) 
    } 
} catch (InterruptedException ex) { 
    // we're outta here! 
} 

Esto no va a consumir CPU significativa ... a menos que haya hecho algo patológico, como llamar ServerSocket.setSoTimeout(int) con un pequeño tiempo de espera.