关于OutputStream类中write(int b)与write(byte[] b)的效率问题

本文探讨了Java中OutputStream的write(int b)与write(byte[] b)的效率差异。通过对源码的分析和测试,发现write(int b)在内部调用write(byte[] b),并频繁申请和释放空间,导致效率较低。主要原因是多次调用socketWrite0方法申请缓冲区,次要原因是锁的获取和释放以及其他操作的开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

据说write(int b)与 write(byte[] b)的效率不一样???测试发现,在发送相同内容的数据时(100000个26),write(int b)确实比write(byte[] b)效率要低,经过一层层查看代码与试验,得知了出现这个问题的原因。

一言以蔽之,write(byte[] b)与write(int a)都在OutputStream的子类SocketOutputStream中被重写,write(int a)中调用了write(byte[] b),而每次调用write(byte[] b),实际上都会申请一段空间来缓存b,假如这段空间的长度为65536,b的长度为65536,a的个数为65536,而则write(byte[] b)需要申请1次长度为65536的空间,而write(int a)则需要申请65536次长度为65536的空间。申请/释放是一个耗费时间的操作,两种方法在传输n个byte时,write(int a)需要申请/释放空间n次,而write(byte[] b)则至多需要两次,总的申请/释放空间不同导致了write(int b)与 write(byte[] b)的效率不同

STEP 1

推测:源码实现方式不同;
求证:不同查看源码,发现write(byte[] b)是调用了write(int b),不应当有效率差别,但是源码注释中说Subclasses are encouraged to override this method and provide a more efficient implementation.
当传送一个很大很大的长度的数组时(length = 10000000,除此之外,每次测试对比,都是100000个int或者长度为100000的byte数组),发现报错位置at java.base/java.net.SocketOutputStream.socketWrite0

通过

System.out.println(outputStream.getClass());

发现object.getOutputStream()返回的OutputStream实例其实是OutputStream的子类SocketOutputStream的实体,查看源码发现write(int b)的实现为

public void write(int b) throws IOException {
        temp[0] = (byte)b;
        socketWrite(temp, 0, 1);
}

write(byte[] b)的实现为

public void write(byte b[]) throws IOException {
        socketWrite(b, 0, b.length);
}

STEP 2

推测:是temp[0] = (byte)b;占用了时间
求证:比较1次传入长度为10000的byte数组,和传入10000次长度为1的byte数组,发现并没有什么明显改善。进入socketWrite方法查看,发现调用了socketWrite0(fd, b, off, len);

private void socketWrite(byte b[], int off, int len) throws IOException {


    if (len <= 0 || off < 0 || len > b.length - off) {
        if (len == 0) {
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值