почему мой PipedOutputStream блокируется? - PullRequest
3 голосов
/ 24 сентября 2010

Я пытаюсь реализовать многопоточный кольцевой буфер с PipedInputStream & PipedOutputStream, но он блокируется каждый раз, когда я добираюсь до 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;

edit: вот полный источник моего сервиса http://pastie.org/1179792

logcat распечатывает:

пытается прочитать
пытаюсь написать

Ответы [ 3 ]

4 голосов
/ 26 февраля 2013

Я столкнулся с той же проблемой и решил ее, переопределив значение по умолчанию PIPE_SIZE в конструкторе PipedInputStream (int) . Метод PipedOutputStream.write (byte [], int, int) блокирует, пока все байты не будут записаны в выходной поток. Это может быть проблема с PIPE_SIZE по умолчанию.

В конце концов, размер имеет значение; -)

0 голосов
/ 24 сентября 2010

Просто избавьтесь от теста, связанного с available ().В любом случае чтение заблокируется, и вам нечего делать, когда данных нет.

0 голосов
/ 24 сентября 2010

Программа не блокирует, просто очень, очень медленная и неэффективная. Он использует 100% CPU. Проблема в if (mTail.available() >= mByteSlave.length) - в большинстве случаев это возвращает false, и вы получаете занятый цикл в этом потоке Если вы можете избавиться от этого, сделайте это. Тогда эта проблема решена. Если вы не можете, это становится сложнее ...

Есть еще одна проблема: PipedInputStream.read возвращает int. Вам необходимо использовать:

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();
                }
            }
        }
    }
}
...