【问题标题】:Thread race condition just hangs while using PipedOutputStream线程竞争条件只是在使用 PipedOutputStream 时挂起
【发布时间】:2016-10-27 14:00:11
【问题描述】:

我正在使用管道输出流将OutputStream 转换为InputStream,因为AWS java sdk 不允许使用OutputStreams 将对象放在S3 上

我正在使用下面的代码,但是,它会间歇性地挂起。此代码位于 Web 应用程序中。目前应用程序没有负载...我只是在我的个人计算机上试用它。

ByteArrayOutputStream os = new ByteArrayOutputStream();
PipedInputStream inpipe = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(inpipe);
try {
   String xmpXml = "<dc:description>somedesc</dc:description>"
   JpegXmpRewriter rewriter = new JpegXmpRewriter();
   rewriter.updateXmpXml(isNew1,os, xmpXml); 
      new Thread(new Runnable() {
          public void run () {
              try {
                  // write the original OutputStream to the PipedOutputStream
                  println "starting writeto"
                  os.writeTo(out);
                  out.close();
                  println "ending writeto"
              } catch (IOException e) {
                  System.out.println("Some exception)
              }
          }
      }).start();
      ObjectMetadata metadata1 = new ObjectMetadata();
      metadata1.setContentLength(os.size());
      client.putObject(new PutObjectRequest("test-bucket", "167_sample.jpg", inpipe, metadata1));
    }
 catch (Exception e) { 
      System.out.println("Some exception")
 }
 finally {
    isNew1.close()
    os.close()
 }

【问题讨论】:

  • 作为参考,这里讨论了这种技术(避免再次复制 BAOS 的内容):stackoverflow.com/a/23874232/14955
  • 你有线程转储(kill -QUIT)吗?
  • 我知道那个解决方案。这就是我从那里得到我的狙击手的地方,这正是我在我的问题中所做的,不是吗?
  • 您使用 BAOS 不会破坏管道流的优势吗?实际上,您应该做的是从您创建的线程中调用rewriter.updateXmpXml(isNew1,out, xmpXml);。请注意,我写的是out,而不是os
  • 我同意@Thilo 的观点,收集到 BAOS 的优点是已知大小并且在上传开始之前知道成功。但是,一旦您将数据存储在 RAM 中,就没有必要再考虑启动另一个线程和在线程之间传递数据的复杂性了,只是为了解决一个愚蠢的 API 限制。

标签: java thread-safety java.util.concurrent java-threads


【解决方案1】:

与其费心启动另一个线程,实例化两个并发类,然后从线程到线程传递数据的复杂性,所有这些都是为了解决所提供的 JDK API 中的一个小限制,您应该只创建一个简单的专门化ByteArrayOutputStream:

class BetterByteArrayOutputStream extends ByteArrayOutputStream {
    public ByteArrayInputStream toInputStream() {
        return new ByteArrayInputStream(buf, 0, count);
    }
}

这会将其转换为不复制的输入流。

【讨论】:

  • 这看起来很有希望。你能再解释一下吗? return 语句中的buf 是什么?在rewriter.updateXmpXml(isNew1,os, xmpXml); 之后我怎么称呼它?
  • Javadoc on bufclient.putObject(new PutObjectRequest("test-bucket", "167_sample.jpg", os.toInputStream(), metadata1));
  • 这似乎有效。这对大文件有效吗?这是否将所有数据都保存在内存中?
  • 这是一个奇怪的问题,因为您的初始解决方案已经将所有内容保存在 RAM 中。这只是重复使用相同的数据。
  • 对。我忘记了。使用管道流并给人一种我不是的错觉。如果这不适用于大文件,那么我将返回到 pipedstreams,但按照您在评论中的建议删除 BAOS。由于某种原因,这对我不起作用。我会发布另一个关于它的问题。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多