4

PipedInputStream と PipedOutputStream を使用してスレッド化された循環バッファーを実装しようとしていますが、Decoder ランナブルで mHead.write に到達すると毎回ロックされます。別のスレッドを使用すると、デッドロックが発生する可能性はないと思いました。

    private class DecoderTask implements Runnable{

    @Override
    public void run() {
        while(!mStop){
            try {
                    Log.d(TAG,"trying to write");
        mHead.write(decode( 0, 1000));
            mHead.flush();
            Log.d(TAG,"Decoded");
            } catch (DecoderException e) {
                Log.e(TAG,e.toString());
            } catch (IOException e) {
                Log.e(TAG,e.toString());
            }
        }
    }

}
private class WriteTask implements Runnable{

    @Override
    public void run() {
        while(!mStop){
            try {
                                 Log.d(TAG,"trying to read");
                 int read = mTail.read(mByteSlave, 0, mByteSlave.length);
                 mAudioTrack.flush();
                                 mAudioTrack.write(mByteSlave,0,read);
                                 Log.d(TAG,"read");                 
            } catch (IOException e) {
                Log.e(TAG,e.toString());
            }
        }
    }

}


//in some function
mTail = new PipedInputStream();
mHead = new PipedOutputStream(mTail);
mByteSlave = new byte[BUF];
mT1 = new Thread(new DecoderTask(), "Reader");
mT2 = new Thread(new WriteTask(), "Writer");
mT1.start();
mT2.start();
return;

編集:これが私のサービスの完全なソースですhttp://pastie.org/1179792

logcat が出力します:

読んで
みる 書いてみる

4

3 に答える 3

5

私は同じ問題を経験し、PipedInputStream(int)コンストラクターのデフォルトのPIPE_SIZEをオーバーライドすることで解決しました。PipedOutputStream.write(byte []、int、int)メソッドは、すべてのバイトが出力ストリームに書き込まれるまでブロックします。これは、デフォルトのPIPE_SIZEで問題になる可能性があります。

結局のところ、サイズは重要です;-)

于 2013-02-26T16:03:20.573 に答える
0

available() を含むテストを取り除くだけです。とにかく読み取りはブロックされ、データがない場合は何もする必要がありません。

于 2010-09-24T10:21:48.743 に答える
0

プログラムはブロックしません。非常に遅く、非効率的です。100% の CPU を使用します。問題はif (mTail.available() >= mByteSlave.length)、これはほとんどの場合 false を返すため、このスレッドでビジー ループが発生することです。これを取り除くことができるなら、それをしてください。その後、この問題は解決されます。それができない場合は、さらに複雑になります...

別の問題があります: PipedInputStream.readint を返します。以下を使用する必要があります。

int len = mTail.read(mByteSlave, 0, mByteSlave.length);
mAudioTrack.write(mByteSlave, 0, len);

それ以外は、このコードに問題は見つかりませんでした。私の完全なテストケースは次のようになります。

import java.io.*;
public class Test2 {
    PipedOutputStream mHead;
    PipedInputStream mTail;
    byte[] mByteSlave = new byte[1024];
    boolean mStop;
    public static void main(String... ar) throws Exception {
        new Test2().run();
    }
    void run() throws Exception {
        mTail = new PipedInputStream();
        mHead = new PipedOutputStream(mTail);
        Thread mT1 = new Thread(new DecoderTask(), "Reader");
        Thread mT2 = new Thread(new WriteTask(), "Writer");
        mT1.start();
        mT2.start();
    }
    class DecoderTask implements Runnable {
        public void run() {
            while (!mStop) {
                try {
                    mHead.write(new byte[3000]);
                    mHead.flush();
                    System.out.println("decoded 3000");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    class WriteTask implements Runnable {
        public void run() {
            while (!mStop) {
                try {
                    int len = mTail.read(mByteSlave, 0, mByteSlave.length);
                    if (len < 0) break; // EOF
                    // mAudioTrack.write(mByteSlave, 0, len);
                    // mAudioTrack.flush();
                    System.out.println("written " + len);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
于 2010-09-24T08:22:45.937 に答える