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

时间:2012-12-19 14:33:46

标签: android multithreading android-handler

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

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

8 个答案:

答案 0 :(得分:162)

如果你正在做的事情是"沉重的"你应该在一个线程中做到这一点。如果你没有在它自己的线程中明确地启动它,那么它将在主(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);
        }
    }   
};

总的来说,带回家是你应该在任何时候使用线程,这可能是长时间运行或非常密集(即任何网络,文件IO,重型算术等)。

答案 1 :(得分:28)

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

有关详细信息,您可能需要check out this article

enter image description here

答案 2 :(得分:18)

Handler在同一个Thread上运行,Thread在另一个线程上运行。

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

如果你想保持主线程可以做其他事情,请使用线程。用于需要花费大量时间的任何事情。

答案 3 :(得分:13)

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

使用:

线程:在saperate(后台)线程中执行任务而不是UI线程。 (有助于解锁UI线程)

处理程序用于在UI和后台线程之间进行通信。

看看这个article

答案 4 :(得分:4)

  

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

     

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

     

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

     

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

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

答案 5 :(得分:2)

  

使用Handler而不是Thread的优点/原因是什么?

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

当你创建一个新的Handler时,它被绑定到创建它的线程的线程/消息队列 - 从那时起,它将消息和runnables传递给该消息队列并执行它们因为他们从消息队列中走出来。

Handler有两个主要用途:

  1. 安排邮件和 Runnables 将来作为某个点执行
  2. 排队要在与您自己不同的线程上执行的操作。
  3. 如果你使用java线程,你必须自己处理一些事情 - 与主线程同步,取消线程等。

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

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

      

    为什么不使用Executor?即使我确实想使用Handler来做到这一点,怎么样?

    参考:Thread Performance article

    某些类型的工作可以简化为高度并行的分布式任务。由于这会产生大量的工作包,AsyncTaskHandlerThread不是合适的类。 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: Toast in a thread

答案 6 :(得分:1)

Handler可与Thread结合使用,以创建排队机制。您可以使用handlerThread Looper

上发布内容

答案 7 :(得分:0)

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