简体   繁体   English

从套接字流读取的线程占用更多的CPU使用率

[英]Thread for reading from socket stream takes more CPU usage

In client socket, I wrote a thread to read the socket's inputStream continuously. 在客户端套接字中,我编写了一个线程来连续读取套接字的inputStream。 Here I have used a while loop to read infinitely. 在这里,我使用了while循环来无限读取。 However it takes more CPU; 但是,它需要更多的CPU。 hence is it possible to reduce the CPU. 因此可以减少CPU。 Please add your suggestions. 请添加您的建议。 Also is it possible to add listeners for inputStream. 也可以为inputStream添加侦听器。

Thread code: 线程代码:

public void run() {
while (!shutdown) {
    try {
        if(socketClient != null) {
            String message = socketClient.getMessage();
            logger.info ("Message size:" + message.length ());
            if(!message.equals("EmptyString")) {
                process(message);
            }
        } 
    } catch (Exception exception) {
        logger.info("Unable to read the socket message" +exception);
    }
}

} }

SocketClient.java SocketClient.java

public class SocketClient{
private volatile boolean isConnected;
private int              port;
private int              retryCount;
private long             startTime;
private String           hostName;
private DataInputStream  input;
private DataOutputStream output;
private Socket           socket;

public SocketClient(int port, String hostname) throws IOException {
    this.port     = port;
    this.hostName = hostname;
    establishConnection();
}


public void shutdown() {
    try {
        shutdown = true;
        input.close();
        output.close();
        socket.close();
    } catch (Exception e) {
        logger.debug("Exception in shutdown:" + e.getMessage());
    }
}

        public String getMessage() {
    BufferedReader reader = null;

    try {
        StringBuilder builder = new StringBuilder();
        reader = new BufferedReader(new 
                        InputStreamReader(tcpSocket.getInputStream()));

        do {
            builder.append(reader.readLine());
        } while((reader.ready()));

        if (builder.length() == 0)
            return "EmptyString";

        return builder.toString();
    } catch (IOException e) {
            return "EmptyString";
    } finally {
        try {
            if(reader != null)
                reader.close();
        } catch(IOException e) {
            logger.error("unable to close reader");
        }
    }
}

    private void establishConnection() {
        retryCount = 1;
        startTime  = System.currentTimeMillis();

        while (!shutdown) {
            try {
                if(!isConnected) {
                    socket = new Socket(hostName,port);
                    socket.setKeepAlive(true);
                    input       = new DataInputStream(socket.getInputStream());
                    output      = new DataOutputStream(socket.getOutputStream());
                    isConnected = true;
                    shutdown    = true;
                } 
            } catch (Exception exception) {
                isConnected = false;
                sleepFewSeconds();
                reconnectSocket();
            }
        }
    }

    private void reconnectSocket() {
        long endTime = startTime + 120000L;

        if(!(System.currentTimeMillis() < endTime)) {
            shutdown = true;
        }   
    }

    private void sleepFewSeconds() {
        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException interruptedException) {
            shutdown = true;
        }
    }

}

I am going to critique the entire class here. 我要在这里批评整个班级。 The answer to your specific question will appear. 您特定问题的答案将会出现。

public class SocketClient{
private volatile boolean isConnected;

You don't need this. 你不需要这个 socket == null would do just as well. socket == null也可以。

private int              port;
private int              retryCount;
private long             startTime;
private String           hostName;
private DataInputStream  input;
private DataOutputStream output;
private Socket           socket;

public SocketClient(int port, String hostname) throws IOException {
    this.port     = port;
    this.hostName = hostname;
    establishConnection();
}


public void shutdown() {
    try {
        shutdown = true;
        input.close();
        output.close();
        socket.close();

You don't need all these closes, and you're doing them in the wrong order anyway. 您不需要所有这些关闭操作,并且您以错误的顺序进行操作。 output.close() is sufficient and in any case it should certainly be first. output.close()就足够了,在任何情况下都应该是第一个。

    } catch (Exception e) {
        logger.debug("Exception in shutdown:" + e.getMessage());
    }
}

public String getMessage() {
    BufferedReader reader = null;

The BufferedReader should be an instance variable, not a local variable. BufferedReader应该是一个实例变量,而不是局部变量。 It's buffered. 它已缓冲。 If you make it a local variable you will lose data. 如果将其设为局部变量,则将丢失数据。

    try {
        StringBuilder builder = new StringBuilder();
        reader = new BufferedReader(new 
                        InputStreamReader(tcpSocket.getInputStream()));

        do {
            builder.append(reader.readLine());
        } while((reader.ready()));

You don't need all this. 您不需要所有这些。 If the message is a single line, all you need is return reader.readLine() , and you need the caller to check whether it was null, and if so close the socket, cease reading, etc. If the message is more than one line, this is a misuse of ready() : it is certainly not an indicator of end of message. 如果该消息是一行,则只需return reader.readLine() ,并且您需要调用方检查它是否为null,如果是,则关闭套接字,停止读取,等等。行,这是对ready()的滥用:它当然不是消息结束的指示。 It appears from comments under your question that you shouldn't even have the method : just connect the socket input stream directly to your XML parser and let it do the reading. 从您的问题下的注释中看来,您甚至都不应该使用该方法 :只需将套接字输入流直接连接到XML解析器,然后由进行读取即可。

        if (builder.length() == 0)
            return "EmptyString";

Don't do this. 不要这样 Return "" or null. 返回""或null。 Don't make up new magic strings for your application to have to decode. 不要为您的应用程序编写新的魔术字符串,而不必对其进行解码。

        return builder.toString();
    } catch (IOException e) {
            return "EmptyString";

Ditto. 同上。

    } finally {
        try {
            if(reader != null)
                reader.close();

You should not close the reader here. 应该在这里关闭的读者。 Closing it will close the socket, so you can never get another message. 关闭它会关闭套接字,所以您再也不会收到任何消息。

        } catch(IOException e) {
            logger.error("unable to close reader");
        }
    }
}

private void establishConnection() {
        retryCount = 1;
        startTime  = System.currentTimeMillis();

        while (!shutdown) {
            try {
                if(!isConnected) {
                    socket = new Socket(hostName,port);
                    socket.setKeepAlive(true);
                    input       = new DataInputStream(socket.getInputStream());
                    output      = new DataOutputStream(socket.getOutputStream());
                    isConnected = true;
                    shutdown    = true;

Why are you setting shutdown to true here? 为什么在这里将shutdown设置为true Nothing is shutdown yet. 尚未关闭任何东西。 It's a brand new socket. 这是一个全新的插座。

                } 
            } catch (Exception exception) {
                isConnected = false;
                sleepFewSeconds();
                reconnectSocket();
            }

Poor practice. 糟糕的做法。 Socket.connect() , which is called internally by new Socket(...) , already retries, and also you should distinguish between connection-failure exceptions rather than adopt the same strategy for them all. new Socket(...)内部调用的Socket.connect()已经重试,并且您还应该区分连接失败异常,而不是对所有异常采用相同的策略。 For example, a 'connection timeout' will already have blocked for a minute or so: you don't need another sleep; 例如,“连接超时”已经阻塞了一分钟左右:您不需要睡觉; and 'connection refused' means there is nothing listening, so retrying is completely pointless. “拒绝连接”意味着没有人在听,因此重试完全没有意义。

    private void reconnectSocket() {
        long endTime = startTime + 120000L;

        if(!(System.currentTimeMillis() < endTime)) {
            shutdown = true;
        }   
    }

    private void sleepFewSeconds() {
        try {
            TimeUnit.MILLISECONDS.sleep(20);

This is not a 'few seconds'. 这不是“几秒钟”。 It is 20 milliseconds , and that is not enough by at least two orders of magnite in network programming, to the extent that there should be any sleep at all of course. 这是20 毫秒 ,在网络编程中,至少要有两个数量级的magnite还是不够的,以至于当然应该保证所有睡眠。

        } catch (InterruptedException interruptedException) {
            shutdown = true;

shutdown appears to be never false. shutdown似乎永远不会错误。 I doubt that you've thought through what it really means, and I doubt that you really need it at all. 我怀疑您是否已经真正考虑了它的含义,并且怀疑您是否真的需要它。

As for your calling code: 至于您的呼叫代码:

public void run() {
while (!shutdown) {
    try {
        if(socketClient != null) {

If socketClient is null this loop will spin meaninglessly. 如果socketClient为null,则此循环将无意义旋转。 Surely this method should construct the socket client? 当然该方法应该构造套接字客户端吗?

            String message = socketClient.getMessage();
            logger.info ("Message size:" + message.length ());

Here you are failing to check for null and failing to respond appropriately, which would be to close the socket and exit the loop. 在这里,您将无法检查null并无法正确响应,这将是关闭套接字并退出循环。 Instead you will get an NPE here. 相反,您将在此处获得NPE。

            if(!message.equals("EmptyString")) {
                process(message);

See above. 往上看。 Don't send yourself special text messages. 不要给自己发送特殊的短信。 What happens if the peer needs to send that one day? 如果对等方需要发送这一天会怎样?

            }
        } 
    } catch (Exception exception) {
        logger.info("Unable to read the socket message" +exception);

Unacceptable. 不能接受的。 This catch is inside the loop and it essentially ignores the exception. 该捕获位于循环内部,并且实际上忽略了异常。 The result is that, again, this loop will spin meaninglessly on any exception. 结果是,再次,此循环将在任何异常情况下无意义地旋转。 And the methods you're calling should be declared to throw IOException , and that is all you should catch here. 并且您要调用的方法应该声明为抛出IOException ,这就是您应该在这里捕获的所有内容。 At present you will spin even on NullPointerException . 目前,您甚至可以旋转NullPointerException

i see you are facing a lot of problem due to high disk usage of your system that many times leads to lagging.Well i have the solution to your problem i found this link on internet..really a helping article http://errorcodespro.com/tiworker-exe-high-disk-usage-windows/ . 我看到由于系统的高磁盘使用率导致许多问题而导致您遇到很多问题。好了,我已经解决了您的问题,我在Internet上找到了此链接。.真的是一个有用的文章http:// errorcodespro。 com / tiworker-exe-high-disk-usage-windows / At begining i thought it was because of hard drive failure but i applied the solution it worked very well. 一开始我以为是因为硬盘驱动器故障,但我采用了很好的解决方案。 You can find your solution at the given system. 您可以在给定的系统上找到您的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM