5

名前付きパイプへの読み取り/書き込みを行う2つのスレッドを持つ同じプロセスの範囲内で、リーダー/ライターをまったくブロックしないと思いますか? タイミングが悪いと、一部のデータを見逃す可能性がありますか?

また、複数のプロセスの場合、リーダーはデータが利用可能になるまで待機し、リーダーが提供するすべてのデータをリーダーが読み取るまでライターはブロックされますか?

名前付きパイプを使用して、外部プロセスからいくつか (数十、数百) のファイルを渡し、Java アプリケーションでファイルを使用することを計画しています。1 つのスレッドをパイプへの書き込み用に使用し、別のスレッドをパイプからの読み取り用に使用する単純な単体テストを作成すると、データ チャンクの欠落が原因で散発的なテスト エラーが発生しました。

スレッド化と同じプロセスが原因だと思うので、私のテストは一般的に正しくありません。この仮定は正しいですか?

以下は、このケースを説明するある種の例です。

import java.io.{FileOutputStream, FileInputStream, File}
import java.util.concurrent.Executors
import org.apache.commons.io.IOUtils
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class PipeTest extends FlatSpec {

  def md5sum(data: Array[Byte]) = {
    import java.security.MessageDigest
    MessageDigest.getInstance("MD5").digest(data).map("%02x".format(_)).mkString
  }

  "Pipe" should "block here" in {
    val pipe = new File("/tmp/mypipe")
    val srcData = new File("/tmp/random.10m")
    val md5 = "8e0a24d1d47264919f9d47f5223c913e"
    val executor = Executors.newSingleThreadExecutor()
    executor.execute(new Runnable {
      def run() {
        (1 to 10).foreach {
          id =>
            val fis = new FileInputStream(pipe)
            assert(md5 === md5sum(IOUtils.toByteArray(fis)))
            fis.close()
        }
      }
    })
    (1 to 10).foreach {
      id =>
        val is = new FileInputStream(srcData)
        val os = new FileOutputStream(pipe)
        IOUtils.copyLarge(is, os)
        os.flush()
        os.close()
        is.close()
        Thread.sleep(200)
    }
  }

}

Thread.sleep(200)がないと、テストに合格できません。

  • 壊れたパイプの例外
  • 不正な MD5 合計

この遅延セットを使用すると、うまく機能します。10 メガバイトのランダム データを含むファイルを使用しています。

4

2 に答える 2

5

これは、コード内の非常に単純な競合状態です。固定サイズのメッセージをパイプに書き込んでおり、同じメッセージを読み戻せると想定しています。ただし、特定の読み取りに対してパイプで使用できるデータの量はわかりません。

書き込みの前に書き込みバイト数を指定し、各読み取りでそのバイト数のみを読み取るようにすると、パイプが宣伝どおりに機能することがわかります。

複数のライターや複数のリーダーがいる場合は、実際のメッセージ キューを使用することをお勧めします。実際には、メッセージ キューを使用することをお勧めします。メッセージ キューを使用すると、メッセージ境界の境界の問題が解決されます。その特定の車輪を再発明してもほとんど意味がありません。

于 2013-05-16T16:52:49.990 に答える
1

名前付きパイプへの読み取り/書き込みを行う2つのスレッドを持つ同じプロセスの範囲内で、リーダー/ライターをまったくブロックしないと思いますか?

非ブロッキング I/O を使用していない限り、そうではありません。

タイミングが悪いと、一部のデータを見逃す可能性がありますか?

非ブロッキング I/O を使用していない限り、そうではありません。

于 2013-05-16T21:07:09.273 に答える