Android: 什么时候应该使用 Handler() ,什么时候应该使用 Thread?

当我需要一些东西来运行 异步的,比如 长时间运行的任务或者使用网络的逻辑,或者不管什么原因, 启动 新线程并运行它可以正常工作。 创建一个 管理员并运行它也可以工作。 有什么区别? 我应该什么时候使用每一个? 使用 Handler而不使用 Thread有什么好处/原因?

- 为了这个问题的缘故,让我们忽略 AsyncTask。 - Handler().postDelayed用例对我来说很清楚,为了这个问题,让我们假设我需要立即开始这个任务。

113908 次浏览

如果您正在做的任何事情都是“重”的,那么您应该在 Thread 中执行它。如果您没有在它自己的线程中显式地启动它,那么它将在主(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);
}
}
};

一般来说,你应该在任何时候使用一个 Thread 来完成一些需要长时间运行或者非常繁重的工作(比如任何网络、文件 IO、繁重的算术等等)。

Handler运行在相同的 Thread上,而 Thread运行在不同的线程上。

如果需要在同一个线程 上运行某些东西,通常是 GUI 元素或类似的东西,请使用 Handler。

如果您想让主线程保持空闲来做其他事情,请使用 Thread。对于任何需要花费大量时间的事情,请使用此选项。

如果需要从新的 Thread 更新用户界面,则需要 与用户界面线程同步。

您可以使用 android.os.Handler 类或 AsyncTasks 类 这个。

Handler 类可以更新用户界面 方法接收 Message 或 Runnable 类的实例。

线程可以通过 sendMessage (Messagemsg)方法发布消息 或者通过 sendEmptyMessage ()方法。

... 更多关于线程等的信息 给你(包括不同的线程和同步机制,以及何时使用什么)

Handler可以与 Thread一起使用,以创建一个 Queued 机制。你可以使用 handlerThread Looper上张贴一些东西

处理程序和线程实际上是两种不同的东西。

必须创建一个线程来执行长时间运行的作业。

Handler 是两个线程之间非常方便的对象(例如: 需要更新 UI 的后台线程)。可以使用 Handler 将一些 Runnable 从后台线程发布到 UI 线程)。

因此,您无法在处理程序和线程之间进行选择。使用一个线程来做繁重的工作!(如果您的后台线程将触发在另一个线程中完成某些作业——大多数时候是 UI 线程,那么您可以使用 Handler)

处理程序是后台线程和 UI 线程之间通信的最佳方式。通常,处理程序与线程的消息队列相关联,用于发送消息,并且可以运行到消息。

使用方法:

线程: 在独立(后台)线程中执行任务,而不是在 UI 线程中(帮助解除 UI 线程的阻塞)

Handler 用于 UI 和后台线程之间的通信。

看看这个 文章

HandlerThread是两个不同的东西,但它们并不矛盾。您可以同时拥有一个 Handler和一个 Thread,实际上每个 Handler必须在一个 Thread中运行。

要了解更多细节,您可能需要 看看这篇文章

enter image description here

使用处理程序而不使用线程有什么好处/原因?

管理员允许您发送和处理与线程的 MessageQueue相关联的 Message 和 Runnable对象。每个 Handler实例都与一个线程和该线程的消息队列相关联。

当您创建一个新的 Handler时,它被绑定到正在创建它的线程的线程/消息队列——从那时起,它将向该消息队列传递消息和可运行消息,并在它们从消息队列中出来时执行它们。

处理程序有两个主要用途:

  1. 将消息和 逃犯作为将来的某个时间点执行
  2. 排队的一个操作将在与您自己的线程不同的线程上执行。

如果你使用 java 线程,你必须自己处理一些事情——与主线程同步,取消一个线程等等。

除非使用 ThreadPoolExecutorExecutorService API,否则这个线程不会创建线程池。

(这个问题来自你对黑带答案的评论)

为什么不使用一个“执行者”? 即使我确实想要使用一个“处理程序”来做到这一点,又该如何做呢?

参考资料: 线程性能文章

某些类型的工作可以简化为高度并行、分布式的任务。由于这样会产生大量的工作包,因此 AsyncTaskHandlerThread不是合适的类。AsyncTask的单线程特性将所有线程池工作转换为线性系统。另一方面,使用 HandlerThread类需要程序员手动管理一组线程之间的负载平衡。

ThreadPoolExecator 是一个帮助器类,可以简化此过程。这个类管理一组线程的创建,设置它们的优先级,并管理工作如何在这些线程之间分配。随着工作负载的增加或减少,该类将旋转或销毁更多线程以适应工作负载。

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

有关更多详细信息,请参阅 创建线程池上的这篇开发人员指南文章。

看看这篇文章,看看如何使用 Handler来运行多个 Runnable 实例。在这种情况下,所有 Runnable任务将在一个线程中运行。

安卓系统: 线中吐司

如果必须在主线程之外单独执行一次任务,则使用 Thread。如果您想重复执行任务,那么 android 提供了一种保持线程活动的方法,并接收消息或 Runnable 对象,以便使用 MessageQueue 中的 Looper 处理这些消息或 Runnable 对象。