为什么写入一个大于Java的PipedInputStream的缓冲区大小的值会导致它无限期地挂起?

z2acfund  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(96)

此Scala代码无限期挂起

import java.io._
import scala.io.Source
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global

def copy(inputStream: InputStream, outputStream: OutputStream): Unit = {
  val buffer = new Array[Byte](1024)
  var bytesRead = inputStream.read(buffer)
  while (bytesRead != -1) {
    outputStream.write(buffer, 0, bytesRead)
    bytesRead = inputStream.read(buffer)
  }
  outputStream.flush()
}

val os0 = new PipedOutputStream
val is0 = new PipedInputStream(os0)

val os1 = new PipedOutputStream
val is1 = new PipedInputStream(os1)

// write to os0
Future {
  os0.write(("foobarbaz"*1000).getBytes("utf-8"))
  os0.close()
}

// copy is0 to os1
Future {
  copy(is0, os1)
  os1.close()
}

// read is1 to output
val result = Source.fromInputStream(is1).mkString
println(result)

但是如果我修改输入数据使其小于1024B缓冲区大小PipedInputStream,则它可以工作,即

os0.write(("foobarbaz").getBytes("utf-8"))

它成功地打印

> foobarbaz

这里发生了什么?管道流实现中是否存在死锁?
Scastie链接:https://scastie.scala-lang.org/131qJRP9Sc6wSVXrqODd2A

46scxncf

46scxncf1#

PipedInputStream/PipedOutputStream组合用于多线程操作,其中读取器和写入器在不同的线程中使用。PipedOutputStream上的写入操作将在缓冲区已满时阻塞,因此它不适用于单线程操作,如复制方法。
您可以只使用StringWriter来缓冲输出以供以后使用。

相关问题