2016-05-11 109 views
9

Ho un codice semplice per un server echo multi-thread in Java (restituisce ciò che è stato restituito ai client). Sto profilando varie risorse del server incluse le statistiche del thread. Di seguito sono riportate alcune di queste statistiche in base al numero di client connessi. Le mie domande riguardano la linea di base (numero di client 0) rispetto alle non di base!Thread daemon, conteggio thread e conteggio totale thread iniziato

1) perché quando un singolo client si connette, il numero totale di thread aumenta di 2? (per il resto, ha senso incrementare di 1)

2) Quali sono i due thread non daemon ?! E perché il demone inizialmente incrementa di 1 e poi viene riparato?

Sono un po 'casuali ?!

# clients     0 1 2 3 4 5 6 7 8 9 10 

Total Started Thread Count 15 18 19 20 21 22 23 24 25 26 27 
Thread count    14 16 17 18 19 20 21 22 23 24 25 
Peak thread count   14 16 17 18 19 20 21 22 23 24 25 
Daemon thread count   12 13 13 13 13 13 13 13 13 13 13 

Ecco il codice del server. Sto usando sia RMI (per i client ai messaggi di polling) che Server Socket (per i client di inviare messaggi). Se sono necessarie altre classi fammi sapere.

package test; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.Vector; 

public class ServerRMI extends Thread implements Hello { 
    //centralized token manager runs polling server and socket server to receive updated tokens 
    static Vector<String> tokenList= new Vector<String>(); 
    protected Socket clientSocket; 
    static int RMIRegistryPort=9001; 
    static int SocketServerPort=9010; 

    public static void main(String[] args) throws IOException { 
     try { 
      ServerRMI obj = new ServerRMI(); 
      Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); 

      // Bind the remote object's stub in the registry 
      Registry registry = LocateRegistry.createRegistry(RMIRegistryPort); 
      registry.bind("Hello", stub); 
      System.err.println("Server ready"); 
     } catch (Exception e) { 
      System.err.println("Server exception: " + e.toString()); 
      e.printStackTrace(); 
     } 

     ServerSocket serverSocket = null; 
     //initialize token list 
     //A needs to execute first 
     tokenList.add(0,"0"); 

     try { 
      serverSocket = new ServerSocket(SocketServerPort); 
      System.out.println("Connection Socket Created"); 
      try { 
       while (true) { 
        System.out.println("Waiting for Connection"); 
        new ServerRMI(serverSocket.accept()); 
       } 
      } catch (IOException e) { 
       System.err.println("Accept failed."); 
      } 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: "+SocketServerPort); 
     } finally { 
      try { 
       serverSocket.close(); 
      } catch (IOException e) { 
       System.err.println("Could not close port: "+SocketServerPort); 
      } 
     } 
    } 

    private ServerRMI(Socket clientSoc) { 
     clientSocket = clientSoc; 
     start(); 
    } 

    public ServerRMI() {}{ 
     // TODO Auto-generated constructor stub 
    } 

    public void run() { 
     System.out.println("New Communication Thread Started"); 

     try { 
      PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), 
        true); 
      BufferedReader in = new BufferedReader(new InputStreamReader(
        clientSocket.getInputStream())); 

      String inputLine; 

      while ((inputLine = in.readLine()) != null) { 
       tokenList.add(0,inputLine); 
       System.out.println("Server received: " + inputLine); 
//     System.out.println(" ququ size: "+queue.size()); 
       out.println(inputLine); 

       if (inputLine.equals("Bye.")) 
        break; 
      } 

      out.close(); 
      in.close(); 
      clientSocket.close(); 
     } catch (IOException e) { 
      System.err.println("Problem with Communication Server"); 
     } 
    } 

    public String pollServer() { 
     if(!tokenList.isEmpty()){ 
      String data = tokenList.get(0); 
      System.out.println("Poll data: "+data); 
      return data; 
     } else{ 
      return tokenList.size()+""; 
     } 
    } 
} 
+0

CAP della tua accetti prega – qwwdfsad

+0

È possibile controllare le informazioni thread nel strumento di profiling che si sta utilizzando. Ad esempio, 'jconsole' o' jvisualvm' mostra tutte le informazioni sul thread nella scheda "Thread". Nel processo verranno eseguiti anche alcuni thread del profiler, che verranno aggiunti al conteggio. –

+1

Non conosciamo il tuo codice, quindi non so come possiamo rispondere. Se fossi in te, farei un dump del thread quando # di client è 0, quando è 1 e li confronta, riceverai la tua risposta –

risposta

3

non sono sicuro quello che si utilizza per ricevere queste connessioni, ma di solito i quadri che gestiscono le connessioni TCP non bloccante come Netty utilizzare un filo maestro per ascoltare il porto e un pool di thread per gestire le connessioni incomming. Ciò significa che aprirà almeno 2 thread per la connessione in entrata se il pool di thread è limitato a 1 thread.

Vedere questo example dalla pagina netty, dove vengono utilizzati 2 NioEventLoopGroups durante l'avvio del server.

I 2 thread sono necessari per non bloccare il traffico in entrata.

+0

Ho aggiunto il pezzo di codice per il server. –

+0

Il codice blocca il thread principale fino a quando il socket riceve una connessione. Cosa succede all'interno di '' start(); '' 'perché questo metodo viene chiamato per la prima volta dopo che una connessione è stata accettata. –

3

Spero solo che tu abbia rivisto i nomi Thread in VisualVM profiler. Di solito i nomi dei thread ti danno un'idea di cosa è stato avviato.

ad 1) questo potrebbe essere un po 'di thread TCP/IP (pulitore, poller) che si genera appena si ha una connessione TCP/IP dall'esterno.

Cosa succede quando i client tornano a 0. Il thread aggiuntivo scompare?

Le risposte possono essere molto diverse a seconda del fornitore e della versione di JVM. Quindi penso che tu abbia bisogno di cercare in interni JVM su socket e thread.

Esempio di seguito è più semplice (senza RMI)

import java.net.*; // for Socket, ServerSocket, and InetAddress 
import java.io.*; // for IOException and Input/0utputStream 

public class TCPEchoServer { 

    private static final int BUFSIZE = 32; // Size of receive buffer 
    public static void main(String[] args) throws lOException { 
     if (args.length != i) // Test for correct # of args 
      throw new lllegalArgumentException("Parameter(s): <Port>"); 
     int servPort = Integer.parselnt(args[0]); 
     // Create a server socket to accept client connection requests 
     ServerSocket servSock = new ServerSocket(servPort); 
     int recvMsgSize; // Size of received message 
     byte[] byteBuffer = new byte[BUFSlZE]; // Receive buffer 

    } 

    for (;;) { // Run forever, accepting and servicing connections 
     Socket clntSock = servSock.accept(); // Get client connection 
     System.out.println("Handling client at " + 
      clntSock.getInetAddress().getHostAddress() + " on port " + 
      clntSock, getPort()); 
     InputStream in = clntSock, getlnputStream(); 
     OutputStream out = clntSock.getOutputStream(); 
     // Receive until client closes connection, indicated by-i return 
     while ((recvMsgSize = in .read(byteBuffer)) != -I) 
      out.write(byteBuffer, O, recvMsgSize); 
     clntSock, close(); 
    } 
} 
+0

Ho aggiunto un pezzo di codice per il server se questo aiuta. –

+0

Ho visto .. Hai davvero bisogno di RMI? Sei a conoscenza della stessa restrizione di sottorete? –

+0

Bene, i client sono in realtà macchine di stato che possono funzionare solo con i dati di polling. RMI è l'unico modo in cui possiamo farlo. –