Java 使用线程的滞后应用程序出现问题

Java 使用线程的滞后应用程序出现问题,java,android,multithreading,Java,Android,Multithreading,我的理解是(如果我偏离了目标,请纠正我),正确使用线程将允许应用程序在高处理器负载的情况下执行多任务 在我的应用程序中,我有一个线程,在其中我处理从相机预览中获取的图像,并尝试进行实时人脸检测,取得了很大的成功。问题在于,与此同时,我希望能够在屏幕上有一个按钮,可以按下该按钮并采取一些行动,而与摄像机检测方法没有任何关系 问题是人脸检测速度很快,但当我按下按钮时,需要一秒钟左右的时间才能做出响应。在没有激活人脸检测线程的情况下(即从未调用start()方法),按钮非常快。下面是我的代码的精简版本

我的理解是(如果我偏离了目标,请纠正我),正确使用线程将允许应用程序在高处理器负载的情况下执行多任务

在我的应用程序中,我有一个线程,在其中我处理从相机预览中获取的图像,并尝试进行实时人脸检测,取得了很大的成功。问题在于,与此同时,我希望能够在屏幕上有一个按钮,可以按下该按钮并采取一些行动,而与摄像机检测方法没有任何关系

问题是人脸检测速度很快,但当我按下按钮时,需要一秒钟左右的时间才能做出响应。在没有激活人脸检测线程的情况下(即从未调用start()方法),按钮非常快。下面是我的代码的精简版本,因为它太长,无法直接发布:

public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        faceThread = new Thread(new Runnable(){
            public void run(){
                //Get camera preview image and detect faces
            }
        });
        faceThread.start();
    }

public void onClickShoot(View v) throws InterruptedException,
            media = new MediaPlayer();
    media.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) {
            media.stop();
            media.reset();
        }
    });
    media.setDataSource(this, dataPath);
    media.prepare();
    media.start();
            //And some other stuff here too.

    }
这只是一个限制,我有这个事实上,这是一个移动平台,我期待太多的延迟?还是有办法让这一切顺利?如果你需要更多关于我正在做什么的信息,请直接问:)

编辑(更多代码以解决问题):

mCamera.setPreviewCallback(new PreviewCallback() {
                    public void onPreviewFrame(final byte[] _data, Camera _camera) {
                        Camera.Parameters parameters = mCamera.getParameters();
                        int format = parameters.getPreviewFormat();
                        // YUV formats require more conversion
                        if (format == ImageFormat.NV21) {
                            int w = parameters.getPreviewSize().width;
                            int h = parameters.getPreviewSize().height;
                            // Get the YuV image
                            YuvImage yuv_image = new YuvImage(_data, format, w, h, null);
                            // Convert YuV to Jpeg
                            Rect rect = new Rect(0, 0, w/3, h); // Rect of the image in which to search for the face
                            final ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
                            yuv_image.compressToJpeg(rect, 10, output_stream);
                            // Convert from Jpeg to Bitmap
                            detectFaces(BitmapFactory.decodeByteArray(
                                    output_stream.toByteArray(), 0,
                                    output_stream.size()));
                            Log.v("TEST", "TEST");
                        }
                    }
                });


public void detectFaces(Bitmap bmp) {
        FaceView faceView = new FaceView(this, bmp);
}

您需要确定争用的位置。它是用于CPU时间,还是用于其他资源?这可能有助于进行一些分析。。。蒂姆·布雷(Tim Bray)最近写了一篇很好的介绍,介绍了如何以及为什么在这里这样做:

值得一提的是,MediaPlayer是出了名的慢而重。你在用什么媒体?您是在给它一个主要存储在内存中的流或缓冲区,还是在通过网络或存储读取媒体时要做大量的I/O工作


出于兴趣,为什么按下按钮后需要人脸检测?也许您可以在启动媒体播放器之前停止线程?

您需要确定争用的位置。它是用于CPU时间,还是用于其他资源?这可能有助于进行一些分析。。。蒂姆·布雷(Tim Bray)最近写了一篇很好的介绍,介绍了如何以及为什么在这里这样做:

值得一提的是,MediaPlayer是出了名的慢而重。你在用什么媒体?您是在给它一个主要存储在内存中的流或缓冲区,还是在通过网络或存储读取媒体时要做大量的I/O工作


出于兴趣,为什么按下按钮后需要人脸检测?也许您可以在启动媒体播放器之前停止线程?

我很确定争用的是CPU时间,因为人脸检测和媒体播放器除了非常小的图像之外没有其他资源。媒体是一个非常小的.wav文件,存储在资源中的原始文件夹中,因此没有重量级流媒体。人脸检测需要在声音播放后立即重新启动,我尝试在线程上使用wait(100)调用,但没有改变延迟的事实。他们停止线程比让线程等待有多大好处?是不是.wav是一种相机快门噪音?不管它是什么,你都是从存储器中加载的。。。这总是需要时间的。建议您在活动启动时将其加载到后台,以便立即开始播放()。更重要的是,不要猜测争用在哪里。。。人们很容易对所有这些API下面发生的事情感到惊讶。使用分析工具找出问题所在!:-)如果您的人脸检测线程没有执行任何IO,那么可能仍然不是CPU争用。它使用什么样的同步来访问像素缓冲区?也许它每秒会锁定1000次缓冲区,迫使UI线程等待很多时间?恐怕魔鬼总是在细节中…这实际上是一个只有100毫秒的枪声。我从你提供的链接中运行了跟踪,看起来它确实使用了75%的CPU时间进行人脸检测,每400毫秒人脸检测需要330毫秒。似乎只有在人脸检测循环完成时,按钮才会起作用。我不认为我可以先设置媒体播放器,因为我要求播放速度快,所以可能一次播放两个实例。我正在使用onPreviewFrame获取用于人脸检测的图像,如果这就是您所说的同步?您的人脸检测必须读取另一个线程(可能)正在填充的缓冲区的内容。在那里的某个地方会有同步,以防止缓冲区在读取时被写入,反之亦然。我不明白为什么你必须创建你的MediaPlayer只是为了响应按钮按下。。。当然,你希望它尽早播放,这样当按下按钮时它就可以播放了。我非常肯定,竞争的焦点是CPU时间,因为人脸检测和mediaPlayer除了非常小的图像外,没有其他资源。媒体是一个非常小的.wav文件,存储在资源中的原始文件夹中,因此没有重量级流媒体。人脸检测需要在声音播放后立即重新启动,我尝试在线程上使用wait(100)调用,但没有改变延迟的事实。他们停止线程比让线程等待有多大好处?是不是.wav是一种相机快门噪音?不管它是什么,你都是从存储器中加载的。。。这总是需要时间的。建议您在活动启动时将其加载到后台,以便立即开始播放()。更重要的是,不要猜测争用在哪里。。。人们很容易对所有这些API下面发生的事情感到惊讶。使用分析工具找出问题所在!:-)如果您的人脸检测线程没有执行任何IO,那么可能仍然不是CPU争用。它使用什么样的同步来访问像素缓冲区?也许它在每秒1000次的缓冲区上获得了一个锁,迫使你的UI死机