2011-03-04 56 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線程(即通過處理程序的多個生產者)接收更新。

相關問題