android.os.Handler 类是否无需将某些方法声明为同步?
在组装一个简单的“时钟”应用程序时,我发现 Android 要求您使用位于线程 A 中的 android.os.Handler,以便使用来自线程 B 的数据结果更新线程 A 中的 View 对象
。对于 Java 来说仍然相对较新,这是我之前第一次显式处理线程,但我知道,如果两个不同的线程想要访问相同的数据,通常您会将方法和/或操作声明为同步。不过, android.os.Handler 似乎是一种 Android 特定的在线程之间同步数据的方法,这样您就可以避免 经典 并发错误< /a> 我刚刚链接到的 Oracle 文档中有详细说明。这是真的吗?
如果我发现自己处于 Android 操作系统要求使用 android.os.Handler 将数据从一个线程传输到另一个线程的情况,这是否意味着我不必这样做将用于派生该数据的方法声明为同步的?
In putting together a simple "Clock" application I discovered that Android requires you to use android.os.Handler that lives in Thread A in order to update View objects in Thread A with the results of data that come from Thread B.
I'm still relatively new to Java, and this is the first time I've dealt explicitly with Threads before, but I know that ordinarily you'd declare methods and/or operations as synchronized if two different threads want to access the same data. It appears though, that android.os.Handler is an Android-specific way of synchronizing data between threads such that you avoid the classic concurrency errors detailed in the Oracle documentation I just linked to. Is this really true?
If I were to find myself in a situation such that I were required by the Android OS to use android.os.Handler to ferry data from one thread to another, does that mean I don't have to declare the methods used to derive that data as synchronized?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的理解:
Handler 只是在两个线程之间传递信息的机制。它不是唯一的机制,但它是 Google 选择使用的机制,用于向 Activity 添加易于使用的方法来执行常见任务。
来自文档
主线程正在运行一个Handler。处理程序负责运行您的活动并管理应用程序环境。 Handler 只是一个消息循环,它从 MessageQueue 中调度事物。这就是为什么你的线程必须运行 Looper 来创建处理程序。要同步您想要用此工作执行的其他操作,您必须将请求插入到此消息队列中,以便主应用程序线程完成您的工作。 ui 的编写方式是,只要只有一个线程访问对象,它就能发挥作用。
我想这样做的目的是指出处理程序是一种进行同步的机制。当然, MessageQueue 的内部结构是为了考虑同步而编写的,尽管“如果多个线程访问它,则需要同步”是一个粗略的简化。尽管 UI 是最常见的示例,但使用 Handler 和 Looper 只是设计多线程应用程序的一种机制,该应用程序为事件处理提供单线程同步。
是否需要同步发送到处理程序的内容很大程度上取决于您发送的内容。如果您正在谈论同步对
post
内容的调用,那么不,处理程序会处理这个问题。如果您正在谈论发布到处理程序的 Runnable 内部的代码,请意识到处理程序的唯一保证是您的 Runnable 将使用创建处理程序的线程执行。您将需要继续提供与其他资源的同步。My understanding:
A Handler is just a mechanism for delivering information between two threads. It's not the only mechanism, but it is the mechanism Google chose to use for adding easy to use methods to Activities to do common tasks.
From the doc
The main thread is running a Handler. The handler is responsible for running your activities and managing the application environment. The Handler is just a message loop which dispatches things from a MessageQueue. This is why your thread has to be running a Looper to create a Handler. To synchronize other stuff you want to do with this effort, you have to insert your requests into this message queue so the main application thread does your work. The ui is written so as long as only one thread accesses the objects, it functions.
I guess the point of this was to point out that the Handler is one mechanism for doing synchronization. Surely, the internals of the MessageQueue are written to take synchronization into account, though its a gross simplification to say 'if multiple threads access it it needs to be synchronized.' Although the UI is the most frequent example, using a Handler and Looper is simply a mechanism for designing a multi-threaded application which provides single thread synchronization for the processing of events.
Whether or not you need to synchronize what you send to a Handler depends greatly on what you are sending. If you are talking about synchronizing the calls to
post
stuff, then no, the handler takes care of that. If you're talking about code inside a Runnable that you post to a Handler, realize that the only guarantee of the Handler is that your runnable will be executed using the thread that created the Handler. You will need to continue to provide synchronization with other resources.仅当您拥有共享资源(例如 ArrayList 或可以同时从两个线程读取的资源)时,才需要同步。
处理程序本身不会阻止任何并发,它只是使执行需要在 UI 线程中发生的事情变得更加容易,即使工作线程正在尝试执行这些操作。
回答您的问题:如果您使用 Handler,通常意味着您在 UI 线程中执行某些关键操作。例如,您有一个在
onCreate
中初始化的ArrayList
,然后可能在点击处理程序或其他内容中进行更新。现在,如果您使用 Handler 来修改它,那么对 ArrayList 的所有访问都将发生在 UI 线程中,因此不需要synchronized
。但是,一旦您从工作线程内访问该 ArrayList,您将需要同步对其的每次访问。
You only ever need
synchronized
if you have a shared resource, like anArrayList
or something that can be read from two threads at the same time.The Handler by itself doesn't prevent any concurrency, it just makes it a lot easier to perform things that need to happen in the UI thread even though a worker thread is trying to do them.
To answer your question: If you use a Handler, it typically means that you do certain critical things in the UI thread. As an example, you have an
ArrayList
that you initialize inonCreate
and then maybe update in a click handler or something. Now if you use a Handler to modify that, then ALL access to the ArrayList will occur in the UI thread, so there is no need forsynchronized
.However, as soon as you access that ArrayList from within a worker thread, you WILL need to synchronize every single access to it.
同步、等待和通知是低级并发结构,在其之上实现了信号量、阻塞队列、屏障和 Looper/Handler 等高级并发结构。
您在 java.util.concurrent (实现高级并发模式/结构)中看到的大部分内容都是在同步、等待和通知(如果您忽略无锁算法)之上实现的
Looper/Handler 机制,基本上是一个轻量级实现生产者-消费者模式,其中有一个消费者但有多个生产者。它的创建是为了在 UI 线程和非 UI 线程之间轻松交换消息。 Android 中的 UI 线程作为单线程循环(即单个消费者)运行,但可以从多个非 UI 线程(即通过处理程序的多个生产者)获取更新。
Synchronized, wait and notify are low level concurrency constructs on top of which high level concurrency constructs like semaphores, blocking queues, barriers and Looper/Handler are implemented.
Most of what you see in java.util.concurrent (which implements high level concurrency patterns/constructs) is implemented on top of synchronized, wait and notify (if you ignore the lock free algorithms)
Looper/Handler mechanism in basically a lightweight implementation of producer-consumer pattern where you have one consumer but multiple producers. It was created to easily exchange messages between the UI thread and non UI threads. UI thread in android runs as a single threaded loop (i.e single consumer) but can take in updates from multiple non UI threads (i.e multiple producers via handlers).