Handler vs AsyncTask vs Thread

Alx*_*Alx 379 multithreading android android-asynctask android-handler

我稍微感到困惑之间的差异Handlers,AsyncTaskThreads在Android中.我在stackoverflow中阅读了很多博客和问题.

Handler是后台线程,提供您与UI进行通信.例如,更新进度条应该通过Handler.使用处理程序可以获得优势MessagingQueues,因此,如果要计划消息或更新多个UI元素或具有重复任务.

AsyncTask类似的,实际上它们使用Handler但不在UI线程中运行,因此它对于获取数据很有用,例如获取Web服务.稍后您可以与UI进行交互.

Thread然而,无法与UI交互,提供更多"基本"线程,你错过了所有的抽象AsyncTask.

但是,我想在服务中运行套接字连接.应该在处理程序或线程中运行,还是在AsyncTask?根本不需要UI交互.它在我使用的性能方面有所不同吗?

与此同时,文件已得到重大改进.

hqt*_*hqt 352

如果你看一下源代码AsyncTaskHandler,你会看到他们的代码是用Java编写的纯粹.(当然,也有一些例外,但这不是重点.)

所以没有魔法AsyncTaskHandler.他们只是让您的工作更容易作为开发人员.

例如:如果程序A调用方法A(),方法A()可以在程序A的不同线程中运行.您可以使用以下方法轻松验证它:

Thread t = Thread.currentThread();    
int id = t.getId();
Run Code Online (Sandbox Code Playgroud)

为什么要使用新线程?你可以google它.原因很多.

那么,是什么样的区别Thread,AsyncTaskHandler

AsyncTask并且Handler是用Java编写的(在内部他们使用a Thread),所以你可以使用的所有东西,Handler或者AsyncTask你可以使用它来实现Thread.

有什么可以HandlerAsyncTask真正的帮助你?

最明显的原因是调用者线程和工作线程之间的通信.(调用者线程:调用工作线程执行某些任务的线程.调用者线程不一定必须是UI线程).当然,您可以通过其他方式在两个线程之间进行通信,但由于线程安全问题,存在许多缺点(和危险).

这就是为什么你应该使用HandlerAsyncTask.他们为您完成大部分工作,您只需要知道要覆盖哪些方法.

Handler和之间的区别AsyncTask是:AsyncTask调用者线程UI线程时使用.这是android文档所说的:

AsyncTask可以正确,方便地使用UI线程.此类允许执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序

我想强调两点:

1)轻松使用UI线程(因此,当调用者线程是UI线程时使用).

2)无需操纵处理程序.(意思是:您可以使用Handler而不是AsyncTask,但AsyncTask是一个更简单的选项).

这篇文章中有很多内容我还没有说过,例如:什么是UI线程,或者为什么它更容易.你必须知道每种方法背后的一些方法并使用它,你将完全理解为什么..

@:当你阅读Android文档时,你会看到:

Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象

起初他们可能看起来很奇怪.只需了解每个线程都有每个消息队列(如待办事项列表),线程将接收每条消息并执行它直到消息队列为空(就像你完成工作并上床睡觉一样).因此,当进行Handler通信时,它只是向调用者线程发出一条消息,它将等待处理.复杂?请记住,它Handler可以安全地与调用者线程通信.

  • 实际上,asynctask也是基于handler和futuretask,[见](参见参考资料)(https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java#L327) (4认同)

Dan*_*l F 56

在Vogella网站上使用Handler,AsyncTask和Loaders进行Android背景处理教程时,可以看到:

Handler类可用于注册到一个线程并提供了一种简单的信道将数据发送到该线程.

所述AsyncTask类封装后台进程的创建,并与主线程同步.它还支持报告正在运行的任务的进度.

而a Thread基本上是多线程的核心元素,开发人员可以使用它具有以下缺点:

如果使用Java线程,则必须在自己的代码中处理以下要求:

  • 如果将结果发布到用户界面,则与主线程同步
  • 取消线程没有默认值
  • 没有默认的线程池
  • 在Android中处理配置更改没有默认值

关于AsyncTask,正如Android Developer's Reference所说:

AsyncTask可以正确,方便地使用UI线程.此类允许执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序.

AsyncTask被设计为围绕一个辅助类ThreadHandler ,并不构成通用线程框架.理想情况下,AsyncTasks应该用于短操作(最多几秒钟.)如果需要保持线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,例如Executor,ThreadPoolExecutor和FutureTask.

2015年5月更新:我发现了一系列涵盖此主题的精彩课程.

这是谷歌搜索:道格拉斯施密特讲的android并发和同步

这是YouTube上第一次讲座的视频

这一切是部分CS 282(2013):系统编程为Android范德比尔特大学.这是YouTube播放列表

道格拉斯施密特似乎是一位出色的讲师

重要提示:如果您正处于考虑用于AsyncTask解决线程问题的位置,则应首先检查ReactiveX/RxAndroid可能更合适的编程模式.获取概述的一个非常好的资源是通过示例学习RxJava 2 for Android.

  • 在该系列讲座中,此链接将带您进入一些线程示例:https://youtu.be/4Vue_KuXfCk?t = 19m24s (4认同)

Lav*_*wal 52

在深入研究之后,它是直截了当的.

AsyncTask:

这是一种使用线程的简单方法,而不了解任何有关java线程模型的信息. AsyncTask给出了与工作线程和主线程相对应的各种回调.

用于小等待操作,如下所示:

  1. 从Web服务获取一些数据并在布局上显示.
  2. 数据库查询.
  3. 当你意识到永远不会嵌套运行操作时.

Handler:

当我们在android中安装应用程序时,它会为该应用程序创建一个名为MAIN UI Thread的线程.所有活动都在该线程内运行.通过android单线程模型规则,我们无法直接访问该元素内部定义的另一个线程的UI元素(位图,textview等).

Handler允许您与其他后台线程的UI线程进行通信.这在android中很有用,因为android不允许其他线程直接与UI线程通信.处理程序可以发送和处理与线程的MessageQueue关联的Message和Runnable对象.每个Handler实例都与一个线程和该线程的消息队列相关联.创建新的Handler时,它将绑定到创建它的线程的线程/消息队列.

它最适合:

  1. 它允许您进行消息排队.
  2. 消息调度.

Thread:

现在是讨论线程的时候了.

线程是双方的父母AsyncTaskHandler.他们都在内部使用的线程,这意味着你还可以创建自己的线程模型AsyncTaskHandler,但是这需要有很好的了解Java的多线程实现.


Eug*_*e S 22

An AsyncTask用于执行一些后台计算并将结果发布到UI线程(带有可选的进度更新).既然你不关心UI,那么a Handler或者Thread似乎更合适.

您可以生成一个背景Thread,并通过传递消息回你的主线程 Handlerpost方法.


Har*_*ake 9

线

Android支持标准Java 线程.您可以使用标准线程和包" java.util.concurrent"中的工具将操作放入后台.唯一的限制是您无法直接从后台进程更新UI.

如果您需要从后台任务更新UI,则需要使用某些特定于Android的类.您可以使用类" android.os.Handler"来表示此类或" AsyncTask"

处理器

类" Handler"可以更新UI.句柄提供接收消息和可运行的方法.要使用处理程序,您必须将其子类化并覆盖handleMessage()以处理消息.要进行处理Runable,您可以使用该方法post();您只需要活动中的一个处理程序实例.

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

的AsyncTask

如果您Activity需要下载内容或执行可在后台执行的操作,则可以AsyncTask维护响应式用户界面并将这些操作的进度发布给用户.

有关更多信息,您可以查看这些链接.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


Rav*_*abu 6

Thread:

您可以将new Thread用于长时间运行的后台任务,而不会影响UI线程.从java Thread,您无法更新UI线程.

由于普通的Thread对Android架构没什么用处,因此引入了用于线程的辅助类.

您可以在线程性能文档页面中找到查询的答案.

处理程序:

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

a有两个主要用途Handler:

  1. 安排消息和runnables作为将来的某个点执行;

  2. 将要在不同于自己的线程上执行的操作排入队列.

AsyncTask:

AsyncTask可以正确,方便地使用UI线程.此类允许您执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序.

缺点:

  1. 默认情况下,应用程序将AsyncTask其创建的所有对象推送到单个线程中.因此,它们以串行方式执行,并且 - 与主线程一样 - 特别长的工作包可以阻塞队列.由于这个原因,使用AsyncTask来处理持续时间小于5 毫秒的工作项.

  2. AsyncTask对象也是隐式引用问题最常见的违规者.AsyncTask对象也存在与显式引用相关的风险.

HandlerThread:

您可能需要一种更传统的方法来在更长时间运行的线程上执行工作块(与AsyncTask不同,它应该用于5ms工作负载),以及一些手动管理该工作流的能力.处理程序线程实际上是一个长时间运行的线程,它从队列中抓取工作并对其进行操作.

ThreadPoolExecutor:

此类管理一组线程的创建,设置其优先级,并管理这些线程之间的工作分配方式.随着工作负载的增加或减少,类会旋转或销毁更多线程以适应工作负载.

如果工作量更大且单个HandlerThread是不够的,你可以去ThreadPoolExecutor

但是,我想在服务中运行套接字连接.它应该在处理程序或线程中运行,还是在AsyncTask中运行?根本不需要UI交互.它在我使用的性能方面有所不同吗?

由于不需要UI交互,因此您可能不会参与AsyncTask.普通线程没有多大用处,因此HandlerThread是最佳选择.由于必须维护套接字连接,因此主线程上的Handler根本没用.创建HandlerThread并获得Handler来自活套HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 
Run Code Online (Sandbox Code Playgroud)

如果要与UI线程进行通信,可以再使用一个处理程序来处理响应.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };
Run Code Online (Sandbox Code Playgroud)

在你的Runnable,你可以添加

responseHandler.sendMessage(msg);
Run Code Online (Sandbox Code Playgroud)

有关实施的更多详细信息,请访问:

Android:在线程中敬酒


Bri*_*ian 5

在我看来,线程不是最有效的套接字连接方式,但它们确实提供了运行线程方面最多的功能.我这样说是因为从经验来看,长时间运行线程会导致设备非常热和资源密集.即使是简单的,while(true)也会在几分钟内加热手机.如果你说UI交互并不重要,也许AsyncTask是好的,因为它们是为长期流程设计的.这只是我对它的看法.

UPDATE

请忽略我的上述答案!我在2011年回答了这个问题,当时我在Android方面的经验远不如我现在.我上面的回答是误导性的,被认为是错误的.我将它留在那里是因为很多人在下面评论它纠正我,我已经吸取了教训.

在这个帖子上有更好的其他答案,但我至少会给我更正确的答案.使用常规Java没有任何问题Thread; 但是,你应该非常小心如何实现它,因为做错了可能会非常耗费处理器(最值得注意的症状可能是你的设备升温).AsyncTask对于您希望在后台运行的大多数任务来说,s非常理想(常见的例子是磁盘I/O,网络调用和数据库调用).但是,AsyncTasks不应该用于特别长的进程,可能需要在用户关闭应用程序或将其设备置于待机状态后继续.我会说,对于大多数情况,任何不属于UI线程的东西都可以在一个AsyncTask.

  • 实际上http://developer.android.com/reference/android/os/AsyncTask.html说:"理想情况下,AsyncTasks应该用于SHORT操作".您也应该小心使用它们,因为它们可以被系统解散而不执行! (15认同)
  • @AeroDroid在你的例子中:"a simple while(true)",除非你在循环中添加一个睡眠状态,否则你将把CPU固定在这里.任何无限循环都是如此.如果由于此开销而希望减少CPU使用率,请在循环结束时将线程休眠几毫秒. (9认同)
  • @Abhijit从我在SDL中完成的游戏中,只需在循环中添加10毫秒的睡眠就足以在空闲状态下从99%cpu降至~0. (6认同)

sky*_*sky 5

AsyncTask被设计为在后台执行不超过几秒的操作(不建议从服务器下载兆字节的文件或计算CPU密集型任务,如文件IO操作).如果需要执行长时间运行的操作,强烈建议您使用java本机线程.Java为您提供了各种与线程相关的类,以满足您的需求.使用Handler更新UI线程.