现在我正在努力提高java I / O的性能。我有一些疯狂的疑问,使用java I / O在网络上读/写流,如下所述。我脑海里浮现出几种意见。但我想清除所有这些
代码
URL url = new URL("http://example.com/connector/url2Service");
URLConnection urlConnection = url.openConnection(); // Position 1
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
String requestStr = buildRequestString();// Position 2
ByteArrayOutputStream rqByteArrayOutputStream = new ByteArrayOutputStream();
rqByteArrayOutputStream.write(((String)requestStr).getBytes()); // Position 3
httpURLConnection.setDoOutput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
rqByteArrayOutputStream.writeTo(httpURLConnection.getOutputStream()); // Position 4
// Waiting for the response.
InputStream inputStream = httpURLConnection.getInputStream(); // Position 5
ByteArrayOutputStream rsByteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) { // Position 6
rsByteArrayOutputStream.write(buffer, 0, length);// Position 7
}
String response = new String(rsByteArrayOutputStream.toByteArray());// Position 8
我的理解
我的问题
参考文献:
答案 0 :(得分:3)
我们可以说请求上传完成了吗? (我相信当执行存在位置4时,这就完成了)
是的,但是你已经浪费了一些ByteArrayOutputStream。只需将请求直接写入连接输出流即可。节省内存和延迟。
我们可以说响应下载完成了什么? (我对第5点和第8点有疑问)
当你从read()方法收到-1时。
当我们退出Point 5时,是否意味着响应已完全下载或刚开始下载?
都不是。请求已写入,您尚未开始加载任何内容,因此未下载任何内容。它可能已经在套接字接收缓冲区中到达,但你看不到它。
网络(带宽)将在何时对性能产生影响? (第5,6,7 ......)
没有一个。在获得-1之前,您正在使用网络带宽。
现在我正在调整InputStream读取代码。如果您有任何建议请分享?
使用更大的缓冲区。你无能为力。
答案 1 :(得分:2)
在建立连接时,请求可以缓冲在系统缓冲区中,因此在您通过位置6之前,请求的发送 - “上传” - 不能保证完成。此时,您知道服务器已收到get请求,因为它现在正在发送响应。传递位置4只意味着您的程序已将请求传递到您自己的系统缓冲区。
收到回复 - “下载”已完成 - 在最后一次到第6位之后,当它返回-1结束流时。
当您退出第5位时,可能已收到或未收到回复。您所做的只是获得对已存在的输入流的显式访问。响应已经完全接收并且已经缓冲在系统TCP缓冲区中,并且可能尚未收到任何响应。
您必须从位置4到位置6的最后一次迭代打开网络资源。在您的代码中,您将继续无限期地保持连接打开状态。退出6/7 while
循环后,您可以通过关闭连接来节省网络资源。
(a)不要打扰rqByteArrayOutputStream。而是将输出流从OutputStreamWriter中的连接包装起来,并将请求字符串直接写入该输出流。这样可以节省几行代码,并删除一次复制请求字符串的迭代。
(b)完成输出流和输入流后调用close(),以释放网络资源。
答案 2 :(得分:2)
JDK Http相关类基于旧的java.io实现。检查HttpURLConnection of OpenJDK处的代码。 (Details on the OpenJDK roots, based on Oracle JDK 7)使用基于操作系统原语的新java.nio实现直接提供了一个全新的性能范围。 NIO =非阻塞IO或事件驱动的IO。
Netty是一个基于java.nio原语构建的高性能网络实现。我参与了一个项目,其中netty被开发用于在太阳刀片硬件上实现5位数性能。可以找到Netty示例http代码here。
来自LMAX的Martin Thompson撰写的另一篇关于ByteArrayOutputStream性能的文章是java serialization。这可以更深入地了解java性能或内置JDK类性能。
这是您要查找的信息,还是由于遗留的JDK代码库而严格使用的java.io?