Android 与其他同类产品相比,HandlerThread的最佳使用

Android 与其他同类产品相比,HandlerThread的最佳使用,android,android-handler,Android,Android Handler,我试图了解使用HandlerThread的最佳用例 根据定义: “用于启动具有循环器的新线程的Handy类。然后可以使用循环器创建处理程序类。请注意,必须仍然调用start()。” 我可能错了,但使用线程、活套和处理程序可以实现类似的功能。那么什么时候应该使用HandlerThread?举个例子会很有帮助。这里是和的源代码链接 如果你看这两个,你会发现一个HandlerThread正是它所说的-一个启动线程的方便方法,它有一个活套。为什么会存在这种情况?因为。HandlerThread只是一种简

我试图了解使用
HandlerThread
的最佳用例

根据定义:

“用于启动具有循环器的新线程的Handy类。然后可以使用循环器创建处理程序类。请注意,必须仍然调用start()。”


我可能错了,但使用
线程
活套
处理程序
可以实现类似的功能。那么什么时候应该使用
HandlerThread
?举个例子会很有帮助。

这里是和的源代码链接

如果你看这两个,你会发现一个
HandlerThread
正是它所说的-一个启动
线程的方便方法,它有一个
活套。为什么会存在这种情况?因为。
HandlerThread
只是一种简单的创建方法。你能用
处理器
线程
活套
复制这个函数吗?从源代码判断,答案是肯定的


执行器是不同的。
Executor
接受提交的可运行任务,然后——猜猜看是什么——执行它们。为什么这是必要的?它让你可以。你什么时候用这个?假设您遇到需要同时执行多个任务的情况。您可以选择使用
执行器
,在单个线程上运行它们,以便连续执行。或者您可以使用固定的线程池,以便同时运行某些线程,但不是所有线程。在这两种情况下,任务的实质——即它实际在做什么——与执行任务的方式是分开的

这是一个现实生活中的例子,它非常方便。注册相机预览帧时,将在
onPreviewFrame()
回调中接收它们。说明在调用线程open(int)的事件上调用此回调

通常,这意味着回调将在主(UI)线程上调用。因此,当菜单被打开、动画被制作成动画、甚至统计数据被打印在屏幕上时,处理巨大像素阵列的任务可能会被卡住

简单的解决方案是创建一个
新HandlerThread()
并将
Camera.open()
委托给这个线程(我是通过
post(Runnable)
完成的,您不需要实现
处理程序。回调

请注意,使用相机的所有其他工作都可以像往常一样完成,您不必将
Camera.startPreview()
Camera.setPreviewCallback()
委托给HandlerThread。为了安全起见,我先等待实际的
Camera.open(int)
完成,然后再继续主线程(或者在更改之前调用
Camera.open()
的任何线程)


所以,如果你从代码开始

try {
    mCamera = Camera.open(1);
}
catch (RuntimeException e) {
    Log.e(LOG_TAG, "failed to open front camera");
}
// some code that uses mCamera immediately
首先将其按原样提取到私有方法中:

private void oldOpenCamera() {
    try {
        mCamera = Camera.open(1);
    }
    catch (RuntimeException e) {
        Log.e(LOG_TAG, "failed to open front camera");
    }
}
不要调用
oldOpenCamera()
,只需使用
newOpencamera()

请注意,如果在打开原始代码后未立即访问mCamera,则不需要整个notify()--wait()线程间通信


更新:这里同样的方法也适用于加速计:

我从未使用过HandlerThread,但也许这篇文章会有所帮助-@TalKanel:谢谢回复。我查看了这篇文章,但它谈到了Executor优于HandlerThread的好处,我完全同意。我的问题更像是什么是使用HandlerThread的最佳用例,这篇文章也解决了这个问题。执行器更灵活,因为它们可以管理线程池。多线程-您需要使用执行器。单线程-您可以使用HandlerThread。不确定这是否重要,因为遗嘱执行人可以涵盖这两种情况。据我所知,HandlerThread只允许您在后台线程上创建一个处理程序,这可以通过其他方式完成。请参阅我的评论-。一般来说,我更喜欢
HandlerThread
s,因为通过
Message
s实现了超级简单的同步。也就是说,它也可能是一个瓶颈。此外,没有什么可以阻止您将ExecutorService与HandlerThreads一起使用。我以前写过一个,没那么难。@Rarw:这实际上是我的问题,如果我们可以用其他方法做事情,那么创建另一个类需要什么呢。我相信在特殊情况下会有一些好处,我需要知道。我认为你的区别是不精确的。您也可以通过Handler.postRunnable提交要执行的任务。实际上,只需更改ThreadFactory和submit()方法,就可以创建一个只使用HandlerThreads的ExecutorService。使用HandlerThreads,跨线程通信变得更容易,而不是任务提交。我想我不清楚。我并不是说有了执行者,任务执行会更容易。相反,执行者的目的是只处理这些任务的执行。手杖线的用途不同。我以后再编辑。那你在哪里关上相机?@Matthias:这是个好问题。如果您的用例允许这样做,请首先在
Activity.onPause()
中释放摄像头,因为根据。但在某些情况下,您可以在onPause()之后使用相机。在这种情况下,您只需要很少的位置,就可以在不同的场景中保持优雅。关闭新的Runnable应该是}@Praveen当然,在这个场景中“静态”没有什么神圣之处context@Praveen:这是您在覆盖
notify()
private void newOpenCamera() {
    if (mThread == null) {
        mThread = new CameraHandlerThread();
    }

    synchronized (mThread) {
        mThread.openCamera();
    }
}
private CameraHandlerThread mThread = null;
private static class CameraHandlerThread extends HandlerThread {
    Handler mHandler = null;

    CameraHandlerThread() {
        super("CameraHandlerThread");
        start();
        mHandler = new Handler(getLooper());
    }

    synchronized void notifyCameraOpened() {
        notify();
    }

    void openCamera() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                oldOpenCamera();
                notifyCameraOpened();
            }
        });
        try {
            wait();
        }
        catch (InterruptedException e) {
            Log.w(LOG_TAG, "wait was interrupted");
        }
    }
}