守护程序线程,线程计数和总启动线程数 [英] Daemon Threads, thread count, and total started thread count

查看:130
本文介绍了守护程序线程,线程计数和总启动线程数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Java中有一个简单的多线程echo服务器代码(它将返回给客户端返回的内容返回)。我正在分析服务器的各种资源,包括线程统计信息。以下是根据已连接客户端数量的一些统计信息。我的问题是基线(客户0的数量)与非基线的比较!

I have a simple code for a multi-threaded echo server in Java (it returns whatever received back to the clients). I'm profiling various resources of the server including the thread statistics. Below are some of these statistics as per number of connected clients. My questions is for the baseline (# of clients 0) compared with non-baselines!

1)为什么当单个客户端连接时,总线程数增加2? (对于其余部分,增加1是有意义的)

1) why when a single client connects, the total thread count increases by 2? (for the rest, it makes sense to increment by 1)

2)两个非守护程序线程是什么?!为什么守护进程最初增加1然后固定?

2) What are the two non-daemon threads?! And why the daemon initially increment by 1 and then is fixed?

它们是随机的吗?!

# 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

这是服务器的代码段。我正在使用RMI(用于客户端轮询消息)和服务器套接字(用于客户端发送消息)。如果需要其他课程,请告诉我。

Here is the piece of code for the server. I'm using both RMI (for clients to poll messages) and Server Socket (for clients to send messages). If other classes are needed let me know.

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()+"";
        }
    }
}


推荐答案

我希望您查看VisualVM Profiler中的线程名称。通常,线程名称可以让您了解启动的内容。

I just hope you reviewed the Thread names in VisualVM profiler. Usually the thread names give you some idea of what is started.

ad 1)这很可能是某些TCP / IP背景(更清晰,轮询)线程产生的只要你从外面有一些TCP / IP连接。

ad 1) this could very well be some TCP/IP background (cleaner, poller) thread that gets spawned as soon as you have some TCP/IP connection from outside.

当客户回到0时会发生什么?额外的线程会消失吗?

What does happen when clients go back to 0. Does extra thread disappear?

答案可能会有很大不同基于JVM供应商和版本。所以我认为你需要查看JVM内部有关套接字和线程的信息。

Answers may very well differ based on JVM vendor and version. So I think you need to look in JVM internals about sockets and threads.

下面的示例更直接(没有RMI)

Example below is more straight forward (without 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();
    }
}

这篇关于守护程序线程,线程计数和总启动线程数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆