2011-03-04 57 views
4

在发布一个简单的“Clock”应用程序时,我发现Android要求您使用位于线程A中的android.os.Handler,以便使用来自线程B的数据结果更新线程A中的View对象。android.os.Handler类是否消除了将某些方法声明为synchronized的需要?

我还是比较新的Java,这是我第一次明确地处理过线程,但我知道,如果两个不同线程想要访问,通常你会声明方法和/或操作同步相同的数据。不过,似乎android.os.Handler是一种特定于Android的线程间数据同步方式,因此您可以避免在我刚刚链接的Oracle文档中详细说明的classicconcurrency errors。这是真的吗?

如果我发现自己在一个情况就是我是需要由Android操作系统使用android.os.Handler从一个线程运送到另一个数据,这是否意味着我没有要申报用于将数据导出为同步的方法?

回答

11

我的理解:

一个Handler仅仅是两个线程之间传递信息的一种机制。这不是唯一的机制,但它是谷歌选择使用的方法,将简单易用的方法添加到“活动”中以执行常见任务。

从DOC

当您 应用程序创建一个进程,它的主线程 专用于运行消息队列 这需要管理 顶级应用程序的照顾对象 (活动,广播接收器等) 以及它们创建的任何窗口。您可以使用 创建您自己的线程,并且 通过Handler与主要的 应用程序线程进行通信。 这是通过调用与之前相同的帖子 或sendMessage方法完成的,但是从新线程调用 。给定的 可运行或消息随后将在处理程序的消息 队列中计划并在适当时进行处理,其中 。

主线程正在运行Handler。处理程序负责运行您的活动并管理应用程序环境。 Handler只是一个从MessageQueue派发事物的消息循环。这就是为什么你的线程必须运行一个Looper才能创建一个Handler。要同步你想要做的这些工作,你必须将你的请求插入到这个消息队列中,这样主应用程序线程才能完成你的工作。只要只有一个线程访问对象,就可以编写ui,它就起作用。

我想这一点是指出,处理程序是做同步的一种机制。当然,MessageQueue的内部编写是为了将同步考虑在内,尽管它简单地说'如果多线程访问它,它需要同步'。尽管UI是最常见的例子,但使用Handler和Looper只是一种设计多线程应用程序的机制,该应用程序为处理事件提供单线程同步。

您是否需要同步发送到Handler的内容很大程度上取决于您发送的内容。如果您正在讨论将呼叫同步到post的东西,那么不需要,处理程序会处理这个问题。如果你正在讨论在一个Runnable中发布到Handler的代码,请认识到Handler的唯一保证是你的runnable将使用创建Handler的线程来执行。您将需要继续提供与其他资源的同步。

+0

这就是我喜欢能够将多个答案标记为正确答案的时代。这也是一个很好的解释。 – scriptocalypse 2011-03-04 20:26:29

+0

此外,这解释了为什么我不需要一个Looper为我的特定示例(处理程序属于活动的“主”线程,它已经有一个活套)。时钟的运行线程使用主要活动的handler.post(runnable);方法。再次感谢您的解释。 – scriptocalypse 2011-03-04 20:49:00

+1

顺便说一句,我检查和'MessageQueue'确实同步。 – bigstones 2012-09-04 13:06:01

3

如果您有一个共享资源,如ArrayList或者可以同时从两个线程读取的东西,则您只需要​​。

Handler本身并不妨碍任何并发性,即使工作线程正在尝试执行,它也只是使执行需要在UI线程中发生的事情变得更容易。

回答你的问题:如果你使用处理程序,它通常意味着你在UI线程中做了某些关键的事情。举个例子,你有一个ArrayList,你在onCreate初始化,然后可能在点击处理程序或更新。现在,如果您使用Handler修改它,那么对UI线程的所有对ArrayList的访问都将发生,因此不需要​​。

但是,只要在工作线程中访问该ArrayList,就需要同步对它的每一次访问。

+0

关注事件处理程序......事实上,时钟本身就是事件调度程序,向感兴趣的各方通知诸如“闹钟已关闭”或“已是午夜”甚至“时间已过,”这是我的新功能时间”。这些事件确实在UI线程中执行,而时钟的运行(以及事件的分派)发生在时钟的运行线程中。同样有趣的是,你提到ArrayLists是因为我有一个包含所有事件处理程序对象的ArrayList,可以通过时钟的运行线程和UI线程访问这些对象。 – scriptocalypse 2011-03-04 19:30:04

0

同步,等待和通知是低级别的并发结构,其上实现了像信号量,阻塞队列,障碍和Looper/Handler这样的高级并发结构。

大多数的你在看的java.util.concurrent(实现高水平并发模式/构造)是在同步上实现的,等待和通知(如果你忽略了无锁算法)

活套/处理程序机制基本上是生产者 - 消费者模式的轻量级实现,其中您有一个消费者但有多个生产者。它的创建是为了轻松地在UI线程和非UI线程之间交换消息。 android中的UI线程作为单线程循环运行(即单个消费者),但可以从多个非UI线程(即通过处理程序的多个生产者)接收更新。

相关问题