142

当我需要异步运行某些东西时,例如长时间运行的任务或使用网络的逻辑,或者出于任何原因,启动一个新线程并运行它可以正常工作。创建一个处理程序并运行它也可以。有什么不同?我应该什么时候使用每一个?使用 aHandler而不是 a的优点/原因是Thread什么?

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

4

9 回答 9

175

如果您正在做的任何事情都是“沉重的”,那么您应该在线程中进行。如果您没有在自己的线程中明确启动它,那么它将在主 (UI) 线程上运行,这可能会导致用户界面抖动或响应缓慢。

有趣的是,当您使用线程时,通常还可以使用 Handler 作为您正在启动的工作线程和主线程之间的通信手段。

典型的 Thread/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);
        }
    }   
};

但总的来说,当你在做一些可能长时间运行或非常密集的工作(即任何网络、文件 IO、繁重的算术等)时,你应该使用线程。

于 2012-12-19T14:40:47.817 回答
75

Handler 和 Thread 真的是两个不同的东西。

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

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

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

于 2012-12-19T14:48:20.187 回答
31

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

有关更多详细信息,您可能需要查看这篇文章

在此处输入图像描述

于 2015-08-03T04:02:32.120 回答
21

AHandler在同一个线程上运行Thread, aThread在不同的线程上运行。

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

如果您想让主线程自由地做其他事情,请使用线程。将其用于需要大量时间的任何事情。

于 2012-12-19T14:40:58.480 回答
16

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

采用:

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

Handler用于在 UI 和 Background 线程之间进行通信。

看看这篇文章

于 2015-03-17T15:30:27.897 回答
4

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

您可以为此使用 android.os.Handler 类或 AsyncTasks 类。

Handler 类可以更新用户界面。处理程序提供用于接收 Message 或 Runnable 类的实例的方法。

您的线程可以通过 sendMessage(Message msg) 方法或 sendEmptyMessage() 方法发布消息。

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

于 2012-12-19T14:41:46.807 回答
2

使用处理程序而不是线程的优点/原因是什么?

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

当您创建一个 newHandler时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们从消息队列中出来时执行它们.

Handler有两个主要用途:

  1. 安排消息和Runnables在未来某个时间点执行
  2. 将要在与您自己的线程不同的线程上执行的操作排入队列。

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

这个单线程不会创建线程池,除非你使用ThreadPoolExecutorExecutorServiceAPI。

(从您对 Blackbelt 答案的评论中获取此查询)

为什么不使用执行器?即使我确实想使用 Handler 来做到这一点,怎么办?

参考:线程性能文章

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

ThreadPoolExecutor是一个帮助类,使这个过程更容易。此类管理一组线程的创建,设置它们的优先级,并管理工作在这些线程之间的分配方式。随着工作负载的增加或减少,该类会启动或销毁更多线程以适应工作负载。

 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的开发者指南文章了解更多详细信息。

查看这篇文章以了解Handler运行多个 Runnable 实例的用法。在这种情况下,所有Runnable任务都将在单个线程中运行。

Android:线程中的吐司

于 2017-08-28T13:07:46.773 回答
1

Handler可以结合使用Thread以创建队列机制。您可以使用handler发布内容Thread Looper

于 2012-12-19T14:43:27.187 回答
0

如果您只需要在主线程之外单独执行一次任务,请使用 Thread. 如果您想重复执行任务,那么 android 提供了一种方法来保持线程处于活动状态并接收消息或 Runnable 对象以使用 MessageQueue 中的 Looper 处理它们。

于 2020-09-23T02:13:31.187 回答