我使用apache客户端向目标服务器执行一些post请求,使用管道流编写内容。因此,基本上,从一个线程,http客户机从PipedInputStream读取,从另一个线程,我在PipedOutputStream上编写内容。
每隔一段时间,我就会看到线程转储,并看到许多线程在java.io.PipedInputStream.read()方法上被阻塞,执行wait(1000)行。阻塞状态意味着读取线程在1000 ms运行后等待获取锁。但我不明白的是,为什么我看不到任何写线程来保存线程转储中的锁。我遗漏了什么,如何避免线程被阻塞?
下面是线程转储文件中的一些行:
Thread 7912: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
- java.io.PipedInputStream.read() @bci=142, line=326 (Compiled frame)
- java.io.PipedInputStream.read(byte[], int, int) @bci=43, line=377 (Compiled frame)
- org.apache.http.entity.InputStreamEntity.writeTo(java.io.OutputStream) @bci=75, line=140 (Compiled frame)
- org.apache.http.impl.execchain.RequestEntityProxy.writeTo(java.io.OutputStream) @bci=10, line=123 (Compiled frame)
- org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) @bci=31, line=156 (Compiled frame)
- org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) @bci=5, line=162 (Compiled frame)
- org.apache.http.protocol.HttpRequestExecutor.doSendRequest(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) @bci=223, line=238 (Compiled frame)
- org.apache.http.protocol.HttpRequestExecutor.execute(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) @bci=25, line=123 (Compiled frame)
- org.apache.http.impl.execchain.MainClientExec.execute(org.apache.http.conn.routing.HttpRoute, org.apache.http.client.methods.HttpRequestWrapper, org.apache.http.client.protocol.HttpClientContext, org.apache.http.client.methods.HttpExecutionAware) @bci=714, line=271 (Compiled frame)
- org.apache.http.impl.execchain.ProtocolExec.execute(org.apache.http.conn.routing.HttpRoute, org.apache.http.client.methods.HttpRequestWrapper, org.apache.http.client.protocol.HttpClientContext, org.apache.http.client.methods.HttpExecutionAware) @bci=447, line=184 (Compiled frame)
- org.apache.http.impl.execchain.RetryExec.execute(org.apache.http.conn.routing.HttpRoute, org.apache.http.client.methods.HttpRequestWrapper, org.apache.http.client.protocol.HttpClientContext, org.apache.http.client.methods.HttpExecutionAware) @bci=39, line=88 (Compiled frame)
- org.apache.http.impl.client.InternalHttpClient.doExecute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) @bci=168, line=184 (Compiled frame)
- org.apache.http.impl.client.CloseableHttpClient.execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) @bci=14, line=82 (Compiled frame)
- org.apache.http.impl.client.CloseableHttpClient.execute(org.apache.http.client.methods.HttpUriRequest) @bci=6, line=107 (Compiled frame)发布于 2017-05-30 09:53:06
当您在一个read()上调用PipedInputStream并且缓冲区为空时,它将在某个对象上阻塞wait(),直到对应的PipedOutputStream写入一些东西并通知PipedInputStream正在等待的任何对象。这只是熟悉的
synchronized (lock)
{
while (...)
lock.wait();
}模式,其中wait()为其他人释放锁,以便同步并通知on。
为什么你要使用管道流,这是另一个谜。他们只是个玩具。
发布于 2017-05-30 09:51:21
当您在InputStream上调用read时,它会等到OutputStream最终得到数据。所以你才会有等着的家伙。因此,它不是关于写入和锁定,而是关于读取和等待,而inputStream将有数据。
https://stackoverflow.com/questions/44258603
复制相似问题