想问一个关于 IO 流的细节 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pocketz
V2EX    Java

想问一个关于 IO 流的细节

  •  1
     
  •   pocketz 1 月 7 日 2913 次点击
    这是一个创建于 91 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题

    如果对一个 InputStream 调用 read 方法,在没有数据可读取的时候,理论上会处于阻塞状态。

    This method blocks until input data is available, end of file is detected, or an exception is thrown.

    那么如果一个 IO 流,曾经有数据可读取但已经被读取完毕,但后续有可能增加可读取的数据,此时调用 read ,是不是仍然属于这里所说的“blocks until input data is available”,也就是,是否会发生阻塞?

    例子

    我获取了 Process 的 InputStream ,里面的内容是这个进程的标准输出(以及错误输出)。
    显然,进程的输出是间断性的,我想知道现有输出已经被读完的情况下,此时再调用 read ,是否还会处于阻塞状态?

     private ProcessBuilder dumpProcessBuilder; ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(1024); ... dumpProcessBuilder.redirectErrorStream(true); ... Process dumpProcess = dumpProcessBuilder.start(); try (InputStream in = procForReader.getInputStream()) { byte[] buf = new byte[1024]; int bytesRead = 0; while ((bytesRead = in.read(buf)) != -1) { output.write(buf, 0, outputBuffer); } } ... 
    12 条回复    2026-01-17 22:17:47 +08:00
    seedhk
        1
    seedhk  
       1 月 7 日
    是的,仍然会
    AoEiuV020JP
        2
    AoEiuV020JP  
       1 月 7 日
    这种比起自己硬想, 不如让 AI 直接写一个能测试这点的代码出来,实际跑一下看看更理解,
    cnhongwei
        3
    cnhongwei  
       1 月 7 日
    进程结束,流就会关闭,你读的时候就返回-1,不可能一直阻塞啊。如果没有关闭,就会阻塞。
    dode
        4
    dode  
       1 月 7 日
    会堵塞到进程退出吧,你测试看看
    BingoXuan
        5
    BingoXuan  
       1 月 7 日
    是的,系统就是这么设计的。除非你设置成异步 IO ,通过多路复用规避
    sockpuppet9527
        6
    sockpuppet9527  
       1 月 7 日
    caller 始终阻塞,直到 producer 端产生新的数据或 producer 端显示调用 Close 。
    Sezxy
        7
    Sezxy  
       1 月 7 日
    只要没读到 EOF 就会一直阻塞
    mmdsun
        8
    mmdsun  
       1 月 7 日 via iPhone
    @BingoXuan Process 的 getInputStream()也能异步 I/O 吗? 我记得 Java 标准库里好像不支持的。
    gongxuanzhang
        9
    gongxuanzhang  
       1 月 7 日
    @Sezxy 正解
    BingoXuan
        10
    BingoXuan  
       1 月 8 日
    @mmdsun
    我只是从系统本身设计出发。理论上底层实现就是堵塞的,应该选择第三方库用 c/c++桥接 epoll/iocp 处理。这也是为什么不喜欢 java 的原因,工作上太多需要面向 OS 编程,Java 并不是一个好选择
    pocketz
        11
    pocketz  
    OP
       1 月 16 日
    @mmdsun getInputStream() 肯定不能异步吧,异步的都在 nio 包里
    对于我的需求,Copliot 的做法是新建了一个线程来专门读写进程的输出,也算是变相的异步读取了 XD
    mmdsun
        12
    mmdsun  
       1 月 17 日 via iPhone
    @pocketz 意思是 Java 没有办法实现 epoll 那样支持 pipe/socket 。只有网络 socket 才支持多路复用和异步。

    差一个 process.getOutputChannel()的 API 。

    不过我怀疑,pipe 没有网卡硬件、DMA 或中断事件源,即使是 c 语言估计也实现不了“真正的多路复用+异步”。具体的就要问下 5 楼的 BingoXuan 了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5568 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VRSION: 3.9.8.5 30ms UTC 08:23 PVG 16:23 LAX 01:23 JFK 04:23
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86