我正在尝试了解using的最佳用例HandlerThread
。
根据定义:
“用于启动具有循环程序的新线程的便捷类。然后可以使用循环程序创建处理程序类。请注意,仍必须调用start()。”
我可能是错的,但类似的功能,我可以通过使用实现Thread
,Looper
和Handler
。那我HandlerThread
什么时候应该使用?一个例子真的很有帮助。
我正在尝试了解using的最佳用例HandlerThread
。
根据定义:
“用于启动具有循环程序的新线程的便捷类。然后可以使用循环程序创建处理程序类。请注意,仍必须调用start()。”
我可能是错的,但类似的功能,我可以通过使用实现Thread
,Looper
和Handler
。那我HandlerThread
什么时候应该使用?一个例子真的很有帮助。
HandlerThread
s,因为通过Message
s实现了超级简单的同步。也就是说,这也可能是瓶颈。此外,没有什么阻止您将ExecutorService与HandlerThreads一起使用。我以前写过一篇,并不难。
Answers:
这是一个实际的示例,其中HandlerThread变得很方便。注册摄像机预览框时,会在onPreviewFrame()
回调中收到它们。该文件解释说,此回调事件线程打开(INT)从被称为上调用。
通常,这意味着将在主(UI)线程上调用回调。因此,当打开菜单,对动画进行动画处理或即使屏幕上打印了统计信息时,处理巨大像素阵列的任务也可能会卡住。
简单的解决方案是创建一个new HandlerThread()
并委托Camera.open()
给该线程(我通过进行了此操作post(Runnable)
,您无需实现Handler.Callback
)。
请注意,使用Camera进行的所有其他工作都可以照常完成,而不必委托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()
:
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");
}
}
}
请注意,如果您没有在打开原始代码后立即访问mCamera,则不需要整个notify() - wait()线程间通信。
Activity.onPause()
,因为根据Activity生命周期,这是保证您的活动从系统收到的唯一回调。但是在某些情况下,可以在onPause()之后使用相机。在这种情况下,您只需要几个位置即可在不同情况下保持优雅。
notify()
这是HandlerThread和Looper的源代码的链接。
如果您看一下两者,您会发现aHandlerThread
正是它所说的-启动Thread
具有a的a的便捷方法Looper
。为什么会存在?因为线程默认情况下没有消息循环。这HandlerThread
只是创建一个可以做到的简单方法。您是否可以使用Handler
,Thread
和复制此函数Looper
-从源代码来看-答案是肯定的。
一个Executor
是不同的。一个Executor
需要提交可运行的任务和-你猜怎么着-执行它们。为什么这是必要的?它使您可以将任务的执行与其实际内容脱钩。你什么时候用这个?假设您遇到需要同时执行多个任务的情况。您可以选择使用Executor
来在单个线程上运行它们,以便按顺序执行它们。或者,您可以使用固定线程池,以使某些(但不是全部)同时运行。在这两种情况下,任务的实质(即任务的实际执行方式)与执行方式是分开的。