2016-05-11 12 views
9

Tôi có một mã đơn giản cho một máy chủ echo đa luồng trong Java (nó trả về bất kỳ thứ gì đã nhận lại cho máy khách). Tôi đang cấu hình các tài nguyên khác nhau của máy chủ bao gồm cả thống kê luồng. Dưới đây là một số thống kê này theo số lượng khách hàng được kết nối. Câu hỏi của tôi là cho đường cơ sở (# của khách hàng 0) so với phi cơ sở!Chủ đề Daemon, chuỗi chỉ số và tổng số chuỗi bắt đầu

1) tại sao khi một khách hàng kết nối, tổng số lượng chỉ tăng 2? (đối với phần còn lại, có ý nghĩa khi tăng thêm 1)

2) Hai chuỗi không phải daemon là gì ?! Và tại sao daemon ban đầu tăng 1 và sau đó là cố định?

Chúng có phải là loại ngẫu nhiên không ?!

# 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 

Đây là đoạn mã cho máy chủ. Tôi đang sử dụng cả hai RMI (cho khách hàng để thông báo thăm dò ý kiến) và Server Socket (cho khách hàng để gửi tin nhắn). Nếu các lớp khác là cần thiết cho tôi biết.

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

bài viết mã của bạn chấp nhận xin – qwwdfsad

+0

Bạn có thể kiểm tra thông tin chủ đề trong công cụ profiling mà bạn đang sử dụng. Ví dụ, 'jconsole' hoặc' jvisualvm' hiển thị tất cả thông tin luồng trong tab "Threads". Sẽ có một số luồng lược tả cũng đang chạy trong tiến trình, sẽ thêm vào số đếm. –

+1

Chúng tôi không biết mã của bạn, vì vậy tôi không biết cách chúng tôi có thể trả lời. Nếu tôi là bạn, tôi sẽ làm một kết xuất chuỗi khi # của khách hàng là 0 sau đó khi nó là 1 và so sánh chúng, bạn sẽ nhận được câu trả lời của bạn –

Trả lời

3

Tôi không chắc chắn những gì bạn sử dụng để nhận được những kết nối, nhưng thường các khuôn khổ có thể xử lý các kết nối TCP non-blocking như Netty sử dụng một sợi tổng thể để lắng nghe các cổng và bể bơi thread để xử lý các kết nối incomming. Điều này có nghĩa là nó sẽ mở ít nhất 2 luồng cho kết nối đang hoạt động nếu nhóm luồng được giới hạn trong 1 chuỗi.

Xem trang này example từ trang netty, nơi 2 NioEventLoopGroups được sử dụng trong khi khởi động máy chủ.

2 chủ đề là cần thiết để không chặn lưu lượng truy cập đến.

+0

Tôi đã thêm đoạn mã cho máy chủ. –

+0

Mã của bạn chặn luồng chính cho đến khi socket nhận được kết nối. Điều gì xảy ra bên trong '' 'start();' '' bởi vì phương thức này được gọi lần đầu tiên sau khi kết nối được chấp nhận. –

3

Tôi chỉ hy vọng bạn đã xem lại tên Chủ đề trong hồ sơ VisualVM. Thông thường các tên luồng cung cấp cho bạn một số ý tưởng về những gì được bắt đầu.

quảng cáo 1) điều này rất có thể là một số nền TCP/IP (sạch hơn, poller) thread được sinh ra ngay sau khi bạn có một số kết nối TCP/IP từ bên ngoài.

Điều gì xảy ra khi khách hàng quay trở lại 0. Chủ đề phụ có biến mất không?

Câu trả lời có thể rất khác nhau dựa trên nhà cung cấp và phiên bản JVM. Vì vậy, tôi nghĩ rằng bạn cần phải tìm trong nội bộ JVM về ổ cắm và chủ đề.

Ví dụ dưới đây là hơn thẳng về phía trước (không 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

Tôi đã thêm một đoạn mã cho máy chủ nếu có. –

+0

Tôi đã thấy .. Bạn có thực sự cần RMI không? Bạn có biết cùng một hạn chế mạng con không? –

+0

Vâng, các khách hàng thực sự là máy nhà nước mà chỉ có thể làm việc bằng cách bỏ phiếu dữ liệu. RMI là cách duy nhất chúng ta có thể làm được. –

Các vấn đề liên quan