有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java需要同步的帮助

我正在创建一个实时流媒体应用程序,但我在某一点上被卡住了。 这是我的代码:

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()终止的过程,因为它需要回调来清除isDecoding。这看起来像是一个僵局

它无法调用onPreviewFrame,因为对象实例已锁定,因此摄影机线程在等待getPicture()完成时被阻止

我说得对吗? 我该如何解决这个问题?因此,我必须再次在PreviewFrame上通知IsDecode=false

非常感谢您的帮助

也投票支持这个,我会悬赏;)


共 (1) 个答案

  1. # 1 楼答案

    mPreviewCallback中的notify()。onPreviewFrame()通知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,但在这次更改之后,可能不需要同步进程。此外,目前还不清楚是谁在设置ispreviewn