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");
}
}
}