代码之家  ›  专栏  ›  技术社区  ›  Nathan Schwermann

为什么我的PipedOutputStream会死锁?

  •  3
  • Nathan Schwermann  · 技术社区  · 14 年前

    我正在尝试用PipedInputStream和PipedOutputStream实现一个线程循环缓冲区,但每次到达时它都会锁定mHead.写入在解码器中运行。我认为使用独立线程时不会出现死锁。

        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打印输出:


    3 回复  |  直到 14 年前
        1
  •  0
  •   Thomas Mueller    14 年前

    程序没有阻塞,只是速度很慢,效率很低。它使用100%的CPU。问题是 if (mTail.available() >= mByteSlave.length) -在大多数情况下,这将返回false,因此在这个线程中会有一个繁忙的循环。如果你能摆脱这个,就去做吧。那么这个问题就解决了。如果你做不到,事情会变得更复杂。。。

    还有一个问题: PipedInputStream.read 返回一个整数。您需要使用:

    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();
                    }
                }
            }
        }
    }
    
        2
  •  5
  •   DraÅ¡ko Kokić chemalarrea    11 年前

    我也遇到过同样的问题,并通过重写默认值来解决它 PIPE_SIZE PipedInputStream(int) 建造师。方法 PipedOutputStream.write(byte[], int, int) 块,直到所有字节都写入输出流。这可能是默认管道大小的问题。

    毕竟,大小确实很重要;-)

        3
  •  0
  •   user207421    14 年前