需要帮助Synchronized

时间:2011-06-21 13:12:53

标签: java android

我正在创建一个实时流媒体应用,但我陷入了某种困境。 所以,这是我的代码:

public synchronized byte[] getPicture(int Width, int Height) {
    FrameWidth = Width;
    FrameHeight = Height;

    try {                           
        while (!isPreviewOn) {
            wait();
        }

        isDecoding = true;
        mAvailableFrame = false;

        c.setOneShotPreviewCallback(mPreviewCallback);                

        while (isDecoding) {
            wait();
        }

    }
    catch (Exception e) {   
        return null;
    }

    mAvailableFrame = false;

    return mCurrentFrame;
}

PreviewCallback mPreviewCallback = new PreviewCallback() {

    @Override
    public synchronized void onPreviewFrame(byte[] data, Camera camera) {
        int width = FrameWidth;
        int height = FrameHeight;

        // API 7
        int[] temp = new int[width*height];
        OutputStream out = new ByteArrayOutputStream();
        Bitmap bm = null;

        raw2jpg(temp, data, width, height);
        bm = Bitmap.createBitmap(temp, width, height, Bitmap.Config.RGB_565);
        bm.compress(CompressFormat.JPEG, 100, out);
        /*ref*/mCurrentFrame = ((ByteArrayOutputStream)out).toByteArray();
        mAvailableFrame = true;
        isDecoding = false;
        notify();                   
    }
};

当调用synchronized getPicture()时,在执行时,没有其他线程可以在该实例上调用synchronized方法。当getPicture()等待isDecoding时,它正在对实例进行锁定。我怀疑setOneShotPreviewCallback()正在执行,并且相机正在尝试在其自己的线程上调用onPreviewFrame(),但因为这也是一个同步方法,它阻止等待getPicture()终止,因为它需要回调到清楚是解码。这看起来像是一个僵局。

它无法调用onPreviewFrame,因为对象实例已被锁定,因此相机线程被阻塞,等待getPicture()完成。

我说错了吗? 我该如何解决这个问题呢?所以我必须再次通知OnPreviewFrame,IsDecoding = false

非常感谢任何帮助。

同时投票,我将给予赏金;)

1 个答案:

答案 0 :(得分:1)

mPreviewCallback.onPreviewFrame()中的notify()通知mPreviewCallback对象监视器,而getPicture()中的wait()在另一个对象监视器上等待 - notify将永远不会释放wait()。您应该定义一个可从两个对象访问的(最终)变量,并在该变量上显式调用wait()和notify()。像这样:

public final Object myMonitor = new Object();

public synchronized byte[] getPicture(int Width, int Height) {
    FrameWidth = Width;
    FrameHeight = Height;

    try {                     
        synchronized(myMonitor) {    
            while (!isPreviewOn) {
                myMonitor.wait();
            }
        }
        isDecoding = true;
        mAvailableFrame = false;

        c.setOneShotPreviewCallback(mPreviewCallback);                

        synchronized(myMonitor) {    
            while (isDecoding) {
                myMonitor.wait();
            }
        }
    }
    catch (Exception e) {   
        return null;
    }

    mAvailableFrame = false;

    return mCurrentFrame;
}

PreviewCallback mPreviewCallback = new PreviewCallback() {

    @Override
    public synchronized void onPreviewFrame(byte[] data, Camera camera) {
        int width = FrameWidth;
        int height = FrameHeight;

        // API 7
        int[] temp = new int[width*height];
        OutputStream out = new ByteArrayOutputStream();
        Bitmap bm = null;

        raw2jpg(temp, data, width, height);
        bm = Bitmap.createBitmap(temp, width, height, Bitmap.Config.RGB_565);
        bm.compress(CompressFormat.JPEG, 100, out);
        /*ref*/mCurrentFrame = ((ByteArrayOutputStream)out).toByteArray();
        mAvailableFrame = true;
        isDecoding = false;
        synchronized(myMonitor) {    
            myMonitor.notify();                   
        }
    }
};

我不知道您正在扩展的API,但可能在此更改后不需要同步进程。此外,还不清楚谁在设置isPreviewOn。