在客户端套接字中,我编写了一个线程来连续读取套接字的inputStream。在这里,我使用了while循环无限读取。但是它需要更多的CPU;因此可以减少CPU。请添加您的建议。 也可以为inputStream添加监听器。
线程代码:
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
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;
}
}
}
答案 0 :(得分:1)
我要在这里批评整个班级。将出现您特定问题的答案。
public class SocketClient{
private volatile boolean isConnected;
你不需要这个。 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();
你不需要关闭所有这些内容,而且无论如何你都会以错误的顺序执行这些操作。 output.close()
就足够了,无论如何它应该是第一位的。
} catch (Exception e) {
logger.debug("Exception in shutdown:" + e.getMessage());
}
}
public String getMessage() {
BufferedReader reader = null;
BufferedReader
应该是实例变量,而不是局部变量。它被缓冲了。如果您将其设为局部变量,则会丢失数据。
try {
StringBuilder builder = new StringBuilder();
reader = new BufferedReader(new
InputStreamReader(tcpSocket.getInputStream()));
do {
builder.append(reader.readLine());
} while((reader.ready()));
你不需要这一切。如果消息是单行,您只需要return reader.readLine()
,并且需要调用者来检查它是否为空,如果关闭套接字,则停止读取等。消息不止一行,这是对ready()
的误用:肯定不是消息结束的指示。从您的问题的评论中可以看出,您甚至不应该使用方法:只需将套接字输入流直接连接到XML解析器,然后让 it 进行读取
if (builder.length() == 0)
return "EmptyString";
不要这样做。返回""
或null。不要为您的应用程序组成新的魔术字符串以进行解码。
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;
为什么在这里设置shutdown
到true
?什么都没有关闭。它是一个全新的插座。
}
} catch (Exception exception) {
isConnected = false;
sleepFewSeconds();
reconnectSocket();
}
糟糕的做法。由Socket.connect()
在内部调用的new Socket(...)
已经重试,您还应该区分连接失败异常,而不是对它们采用相同的策略。例如,连接超时&#39;已经被阻止了一分钟左右:你不需要另一个睡眠;并且&#39;连接被拒绝&#39;意味着没有任何倾听,所以重试是完全没有意义的。
private void reconnectSocket() {
long endTime = startTime + 120000L;
if(!(System.currentTimeMillis() < endTime)) {
shutdown = true;
}
}
private void sleepFewSeconds() {
try {
TimeUnit.MILLISECONDS.sleep(20);
这不是几秒钟。它是20 毫秒,并且在网络编程中至少有两个级别的数量是不够的,当然应该有任何睡眠。
} catch (InterruptedException interruptedException) {
shutdown = true;
shutdown
似乎永远不会错。我怀疑你是否已经考虑过它的真正意义,我怀疑你真的需要它。
至于你的主叫代码:
public void run() {
while (!shutdown) {
try {
if(socketClient != null) {
如果socketClient
为空,则此循环将无意义地旋转。当然这个方法应该构造套接字客户端吗?
String message = socketClient.getMessage();
logger.info ("Message size:" + message.length ());
这里你没有检查null并且没有正确响应,这将关闭套接字并退出循环。相反,你会在这里得到一个NPE。
if(!message.equals("EmptyString")) {
process(message);
见上文。不要给自己发送特殊的短信。如果同伴需要发送一天会发生什么?
}
}
} catch (Exception exception) {
logger.info("Unable to read the socket message" +exception);
不可接受的。这个catch在循环中,它基本上忽略了异常。结果是,再次,这个循环将在任何异常上无意义地旋转。你要调用的方法应该被声明抛出IOException
,这就是你应该抓住的全部内容。目前你甚至会在NullPointerException
上旋转。
答案 1 :(得分:-1)
我发现你面临很多问题,因为你的系统磁盘使用率很高,很多时候会导致滞后。我有解决你的问题的方法我在互联网上找到了这个链接..真是一篇帮助文章{{3 }}。在开始时我认为这是因为硬盘驱动器故障,但我应用了解决方案,它工作得很好。您可以在给定系统中找到您的解决方案。