Android:什么时候应该使用Handler(),什么时候应该使用Thread?
当我需要asynchronous运行的东西,比如长时间运行的任务或者使用networking的逻辑,或者出于任何原因,启动一个新线程并运行它可以正常工作。 创build一个处理程序并运行它也可以。 有什么不同? 我应该什么时候使用每一个? 使用Handler
而不是Thread
的优点/原因是什么?
PS。 – 为了这个问题,让我们忽略AsyncTask
。 – Handler().postDelayed
用例对我来说很清楚,为了这个问题,我们假设我需要立即启动任务。
如果你正在做的是“沉重”,你应该在一个线程中做。 如果您没有在自己的线程中明确地启动它,那么它将在主(UI)线程上运行,这可能会引起用户的紧张或响应速度缓慢。
有趣的是,当你使用一个线程时,通常也可以使用一个Handler作为你正在启动的工作线程和主线程之间的通信方式。
一个典型的线程/处理程序交互可能看起来像这样:
Handler h = new Handler(){ @Override public void handleMessage(Message msg){ if(msg.what == 0){ updateUI(); }else{ showErrorDialog(); } } }; Thread t = new Thread() { @Override public void run(){ doSomeWork(); if(succeed){ //we can't update the UI from here so we'll signal our handler and it will do it for us. h.sendEmptyMessage(0); }else{ h.sendEmptyMessage(1); } } };
一般来说,拿回家就是你应该使用一个线程,任何时候你正在做一些可能是长时间运行或非常密集的工作(即任何networking,文件IO,重算术等)。
处理程序和线程真的是两回事。
必须创build一个线程才能执行长时间运行的作业。
Handler是一个非常方便的对象,用于在2个线程之间进行通信(例如:后台线程需要更新UI,可以使用Handler从后台线程向UI线程发送一些Runnable)。
所以你没有Handler或Thread之间的select。 用一个线程做重工作! (如果你的后台线程会触发一些工作在另一个线程中完成,你可以使用一个处理程序 – 大部分时间是UI线程)
Handler
和Thread
是两个不同的东西,但它们并不矛盾。 您可以同时拥有一个Handler
和一个Thread
,实际上每个Handler
必须在一个Thread
运行。
欲了解更多详情,你可能想看看这篇文章 。
Handler
在同一个Thread
运行, Thread
在另一个线程上运行。
如果你需要在同一个线程上运行一些东西 ,通常是一个GUI元素或类似的东西,那就使用Handler 。
如果你想让主线程自由地做其他事情,可以使用线程 。 将此用于需要大量时间的任何事情。
处理程序是背景和UI线程之间沟通的最佳方式。 通常,处理程序与线程的消息队列相关联,它们用于发送消息并可以运行到消息。
使用:
线程:在比UI线程执行任务(背景)线程中执行任务。 (有助于取消屏蔽UI线程)
处理程序用于在UI和后台线程之间进行通信。
看看这篇文章
如果您需要从新线程更新用户界面,则需要与用户界面线程同步。
您可以使用android.os.Handler类或AsyncTasks类。
Handler类可以更新用户界面。 Handler提供了接收Message或Runnable类的实例的方法。
你的线程可以通过sendMessage(Message msg)方法或通过sendEmptyMessage()方法发布消息。
…关于线程等的更多信息(包括针对不同线程和同步机制的turorials以及何时使用什么)
使用处理程序而不是线程的优点/原因是什么?
Handler允许您发送和处理与线程的MessageQueue
关联的Message和Runnable
对象。 每个Handler
实例都与单个线程和该线程的消息队列相关联。
当你创build一个新的Handler
,它绑定到正在创build它的线程的线程/消息队列 – 从这一点开始,它将把消息和可运行的消息传递给消息队列,并在消息出来时执行它们队列。
处理程序有两个主要用途:
- 将日程安排消息和Runnables作为将来的某个点执行
- 排队要在不同于自己的线程上执行的操作。
如果你使用java线程,你必须自己处理一些东西 – 与主线程同步,取消线程等。
除非使用ThreadPoolExecutor
或ExecutorService
API,否则此单个线程不会创build线程池。
(从你对Blackbelt的评论中回答这个问题)
为什么不使用Executor? 即使我真的想用Handler来做到这一点,怎么样?
参考: 线程性能文章
有一些types的工作可以降低到高度并行的分布式任务。 随着工作包的大量创build, AsyncTask
和HandlerThread
不是合适的类。 AsyncTask
的单线程性质将把所有线程化的工作转化为线性系统。 另一方面,使用HandlerThread
类将要求程序员手动pipe理一组线程之间的负载平衡。
ThreadPoolExecutor是一个帮助类,使这个过程更容易。 这个类pipe理一组线程的创build,设置它们的优先级,并pipe理这些线程之间的工作分配方式。 随着工作量的增加或减less,这个类会加速或破坏更多的线程以适应工作负载。
BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size ThreadPoolExecutor executor = new ThreadPoolExecutor( Runtime.getRuntime().availableProcessors(), // Initial pool size Runtime.getRuntime().availableProcessors(), // Max pool size 1, // KEEP_ALIVE_TIME TimeUnit.SECONDS, // KEEP_ALIVE_TIME_UNIT workQueue);
你可以参考这篇关于create-threadpool的开发者指南文章来获得更多的细节。
看看这个post使用Handler
来运行多个Runnable实例。 在这种情况下,所有可运行任务将在单个线程中运行。
Android:在一个线程中吐司
Handler
可以与Thread
一起使用以创buildQueued机制。 你可以使用handler
在Thread
Looper
上发布一些东西
- 如何从命令行添加外部jar库到一个android项目
- 在Google地图版本2中将可绘制的图像设置为标记
- android.content.res.Resources $ NotFoundException:无法find资源ID#0xffffffff
- 导航抽屉 – 禁止点击抽屉后面的物品
- 如何在devise支持库的TabLayout中的Tabs之间设置分隔符?
- RecyclerView崩溃时,“报废或附加的意见可能无法回收”
- android – 没有内容提供者的CursorLoader&SQLite
- Android:如何在保持宽高比的同时将图像拉伸到屏幕宽度?
- 多个button的OnClickListener()机器人