Java 为什么我的PipedOutStream会死锁?

Java 为什么我的PipedOutStream会死锁?,java,android,inputstream,outputstream,blocked-threads,Java,Android,Inputstream,Outputstream,Blocked Threads,我试图用PipedInputStream和PipedOutputStream实现一个线程循环缓冲区,但每次我在解码器中运行mHead.write时,它都会被锁定。我认为在使用单独的线程时不会出现死锁 private class DecoderTask implements Runnable{ @Override public void run() { while(!mStop){ try {

我试图用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;
编辑:这是我的服务的完整来源

logcat打印出:

正在尝试阅读

试着写

程序不会阻塞,只是速度很慢,效率很低。它使用100%的CPU。问题是
如果(mTail.available()>=mbytesavail.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();
                }
            }
        }
    }
}
import java.io.*;
公共类Test2{
管道出口;
哌啶;
字节[]mbytesave=新字节[1024];
布尔mStop;
公共静态void main(字符串…ar)引发异常{
新建Test2().run();
}
void run()引发异常{
mTail=新的PipedInputStream();
mHead=新管道输出流(mTail);
线程mT1=新线程(新解码任务(),“读取器”);
线程mT2=新线程(新WriteTask(),“Writer”);
mT1.start();
mT2.start();
}
类DecoderTask实现可运行{
公开募捐{
而(!mStop){
试一试{
mHead.write(新字节[3000]);
mHead.flush();
System.out.println(“解码3000”);
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
}
类WriteTask实现可运行{
公开募捐{
而(!mStop){
试一试{
int len=mTail.read(mbytesave,0,mbytesave.length);
如果(len<0)中断;//EOF
//mAudioTrack.write(mbytesave,0,len);
//mAudioTrack.flush();
System.out.println(“写入的”+len);
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
}
}

只需摆脱涉及available()的测试。无论如何,读取都会被阻塞,当没有数据时,您没有更好的事情可做。

我也遇到过同样的问题,并通过重写构造函数中的默认值来解决它。方法阻塞,直到所有字节都写入输出流。这可能是默认管道大小的问题


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

仍然不工作我编辑了上面的代码以反映我现在的情况,日志输出显示:尝试写入尝试读取,然后什么都没有,它阻塞了读取和写入。问题是您指出的,以及写入(字节[])不是由PipedoutpStream定义的,因此它不工作,您必须使用(字节[],int,int)一个这不像我想象的那样工作,一旦我从mTail读取数据如何清除数据,它会一遍又一遍地读取相同的数据。你不需要清除数据,你只需要确保不会将相同的数据一遍又一遍地写入mAudioTrack和mHead。我更新了代码:写入音频时需要使用“len”:mAudioTrack.write(mbytesave,0,len);-此外,我还添加了EOF检测:if(len<0)break-因此您也可以在WriteTask中删除if(!mStop),但您需要关闭mHead。无法删除mStop这是针对internet广播流的,因此从来没有EOF。对于这种情况,有更好的类吗?
PIPE\u SIZE
是1024,使用1024*2为我解决了这个问题