假设我们有套接字客户端,它正在进行读写操作。执行操作发送和接收有两个线程(请求发送方/响应接收方)。这些线程逐个运行Junit测试用例(如一些压力测试,简单查询)。对于我的情况,我正在运行客户端,它将在DB端和它自己的端之间建立套接字通信。在此逻辑中,请求发送方线程将请求发送到DB端(将请求写入套接字),接收方线程通过读取套接字接收响应(从套接字读取响应)。随机出现实际问题。假设请求发送方线程发送请求,响应接收方尚未收到发送请求的另一端的响应。在此期间,如果任何其他测试用例(我的意思是请求线程)启动(在特定超时期限之后,如果没有来自DB结束的响应)发送其请求并执行执行装置,则响应接收器线程具有< / p>
byte[] ofsRes = new byte[size];
此部分将收到jVm内存不足错误。我怀疑同时读取响应接收器线程导致了这个问题,在堆中分配更多大小的字节对象。
从套接字读取数据
int size = dataInputStream.readInt();
你能帮助任何人解决这个问题的内存错误/可能是线程的并发,即使我使用synchronized。但没有用。让我知道你是否需要任何东西。
private static class ResponseReceiver implements Runnable {
private InputStream _in;
private List<String> _responses = new ArrayList<String>();
private int _expectedCount;
private volatile boolean _finished = false;
public ResponseReceiver(InputStream in, int expectedCount) {
_in = in;
_expectedCount = expectedCount;
}
public List<String> getResponses() {
return _responses;
}
public void run() {
DataInputStream dataInputStream = new DataInputStream(_in);
try {
while (true) {
_logger.info("_responses.size() >= _expectedCount : -> " + (_responses.size() >= _expectedCount) +
" : " + "_responses.size() -> " + _responses.size() + " : " + "_expectedCount -> " + _expectedCount);
if (_responses.size() >= _expectedCount) {
_finished = true;
return;
}
int size = dataInputStream.readInt();
_logger.info("size captured : " + size);
if (size > 0) {
int readSize = 0;
_logger.info( " ofsRes Creating with this size : " + size);
**byte[] ofsRes = new byte[size];**
while (size > 0) {
_logger.info( " Buffer Creating with this size : " + size);
byte[] buffer = new byte[size];
int bufferSize = _in.read(buffer);
_logger.info( " Reading data created Buffer Size : " + bufferSize);
System.arraycopy(buffer, 0, ofsRes, readSize,
bufferSize);
readSize += bufferSize;
_logger.info( " readSize (readSize += bufferSize): " + readSize);
size -= bufferSize;
_logger.info( " size (size -= bufferSize): " + size);
}
_responses.add(new String(ofsRes));
_logger.info("ofsRes added..");
}
}
} catch (IOException e) {
throw new RuntimeException("Error reading data from socket: "
+ e.getMessage());
}
}
}
执行顺序的跟踪:
2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver run 信息:_responses.size()&gt; = _expectedCount: - &gt; false:_responses.size() - &gt; 905:_expectedCount - &gt; 1000 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:捕获的大小:1529 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:ofsRes使用此尺寸创建:1529 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:缓冲区使用此大小创建:1529 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:读取数据创建缓冲区大小:1529 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:readSize(readSize + = bufferSize):1529 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 INFO:size(size - = bufferSize):0 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:ofsRes添加.. 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 INFO:_responses.size()&gt; = _expectedCount: - &gt; false:_responses.size() - &gt; 906 :_ expectedCount - &gt; 1000
假设测试用例正在运行,等待响应* ** * ** (906)
2013年5月27日上午11:45:13 com.xxx.tocf.test.SocketClientTest ofsmlEnqSimpleTest13 INFO:OFSML 13简单查询测试正在进行中......
另一个案例已启动
2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient发送 信息:System.currentTimeMillis(): - &gt; 1369635313336:System.currentTimeMillis() - startTime: - &gt; 0:超时 - &gt; 5000:startTime - &gt; 1369635313336:condition:true 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:_responses.size()&gt; = _expectedCount: - &gt; false:_responses.size() - &gt; 0:_expectedCount - &gt; 1
*假设可能存在不同的阅读*
2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver run 信息:捕获的大小:195399 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:捕获的大小:1195528239 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 INFO:ofsRes使用此尺寸创建:195399 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:ofsRes使用这个大小创建:1195528239 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:缓冲区使用此大小创建:195399 线程中的异常&#34;线程-22&#34; java.lang.OutOfMemoryError:Java堆空间 在com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver.run(SocketClient.java:147) 在java.lang.Thread.run(Thread.java:662) 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:读取数据创建缓冲区大小:759 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:readSize(readSize + = bufferSize):759 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:size(size - = bufferSize):194640 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:缓冲区使用此大小创建:194640 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:读取数据创建缓冲区大小:1533 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:readSize(readSize + = bufferSize):2292 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:size(size - = bufferSize):193107 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:缓冲区使用此大小创建:193107 2013年5月27日上午11:45:13 com.xxx.tocf.test.socket.SocketClient $ ResponseReceiver运行 信息:读取数据创建缓冲区大小:767
答案 0 :(得分:0)
假设发送方线程是否等待来自另一端的特定响应。
为什么呢?你已经有了一个接收器线程。
在此期间,如果任何其他测试用例(我的意思是线程)开始推送他们的请求并执行执行意味着,响应接收器线程具有逻辑
byte[] ofsRes = new byte[size];
size
的价值来自哪里?发送者线程和接收者线程试图读取响应的含义究竟是什么?我不知道你期望发生什么,但将发生的事情是完全未定义的。这没有任何意义。您需要决定谁应该阅读响应,让他们阅读。可能您需要在发送方和接收方线程之间引入一些同步,以便发送方不会发送下一个请求,直到接收方收到前一个请求的结果为止。更好的是,摆脱接收器线程,让发送线程收到自己的响应。
此部分将收到jVm内存不足错误。
当然会的。从某个地方获得size
的基本随机值并尝试分配一定量的内存,因此也是随机的。
我怀疑同时读取响应接收器线程导致了这个问题,在堆中分配了更多大小的字节对象。
再一次。解决方案不是这样做的。