2016-05-11 22 views
9

Ich habe einen einfachen Code für einen Multi-Thread-Echo-Server in Java (er gibt zurück, was auch immer zurück zu den Clients empfangen wurde). Ich profile verschiedene Ressourcen des Servers einschließlich der Thread-Statistiken. Im Folgenden finden Sie einige dieser Statistiken nach Anzahl der verbundenen Clients. Meine Fragen beziehen sich auf die Baseline (Anzahl der Clients 0) im Vergleich zu Nicht-Baselines!Daemon-Threads, Thread-Anzahl und insgesamt gestartete Thread-Anzahl

1) Warum erhöht sich die Gesamtzahl der Threads, wenn ein einzelner Client verbunden wird, um 2? (Für den Rest ist es sinnvoll, um 1 zu erhöhen)

2) Was sind die zwei Nicht-Daemon-Threads ?! Und warum wird der Daemon zunächst um 1 erhöht und dann behoben?

Sind sie irgendwie zufällig ?!

# 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 

Hier ist das Stück Code für den Server. Ich benutze sowohl RMI (für Clients, um Nachrichten abzufragen) und Server-Socket (für Clients, um Nachrichten zu senden). Wenn andere Klassen benötigt werden, lass es mich wissen.

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

Postleitzahl Ihres akzeptieren bitte – qwwdfsad

+0

Sie können die Fadeninformationen in dem Profilierungswerkzeug überprüfen, die Sie verwenden. Zum Beispiel zeigt 'jconsole' oder' jvisualvm' alle Thread-Informationen auf der Registerkarte "Threads" an. Es werden auch einige Profilerthreads ausgeführt, die zur Zählung hinzugefügt werden. –

+1

Wir kennen Ihren Code nicht, daher weiß ich nicht, wie wir antworten können. Wenn ich Sie wäre, würde ich einen Thread-Dump tun, wenn # Client 0 ist, dann wenn es 1 ist und vergleichen Sie sie, erhalten Sie Ihre Antwort –

Antwort

3

Ich bin mir nicht sicher, was Sie diese Verbindungen erhalten verwenden, aber in der Regel Frameworks, die TCP-Verbindungen nicht blockierende wie Netty verwenden, um einen Master-Thread Griff zum Hafen und ein Thread-Pool zu behandeln incomming Verbindungen zu hören. Dies bedeutet, dass mindestens 2 Threads für die eingehende Verbindung geöffnet werden, wenn der Thread-Pool auf 1 Thread beschränkt ist.

Sehen Sie diese example von der netty Seite, wo 2 NioEventLoopGroups beim Bootstrapping des Servers verwendet werden.

Die 2 Threads sind erforderlich, um eingehenden Datenverkehr nicht zu blockieren.

+0

Ich habe den Code für den Server hinzugefügt. –

+0

Ihr Code blockiert den Haupt-Thread, bis der Socket eine Verbindung erhält. Was passiert in '' 'start();' '', weil diese Methode das erste Mal aufgerufen wird, nachdem eine Verbindung akzeptiert wurde. –

3

Ich hoffe nur, dass Sie die Thread-Namen in VisualVM Profiler überprüft haben. Normalerweise geben die Thread-Namen eine Vorstellung davon, was gestartet wurde.

ad 1) Dies könnte sehr gut ein TCP/IP-Hintergrund (sauberer, Poller) Thread sein, der hervorgebracht wird, sobald Sie eine TCP/IP-Verbindung von außen haben.

Was passiert, wenn Clients auf 0 zurückgehen. Wird zusätzlicher Thread entfernt?

Die Antworten können je nach JVM-Hersteller und Version sehr unterschiedlich sein. Ich denke, Sie müssen in den JVM-Interna nach Sockets und Threads suchen.

Beispiel weiter unten noch mehr geradlinig (ohne 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

Ich habe ein Stück Code für den Server hinzugefügt, wenn das hilft. –

+0

Ich sah .. Brauchen Sie wirklich RMI? Sind Sie sich der gleichen Subnetzeinschränkung bewusst? –

+0

Nun, die Clients sind eigentlich State-Maschinen, die nur durch Abfragen von Daten arbeiten können. RMI ist der einzige Weg, wie wir es schaffen können. –