1. 程式人生 > >Android Handler 傳送訊息的執行緒安全問題

Android Handler 傳送訊息的執行緒安全問題

Handler在多執行緒傳送訊息到訊息佇列時是否會產生執行緒安全問題。

下面對傳送流程進行分析

 public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); }
請注意這段程式碼 
MessageQueue queue = mQueue;
handler獲取了Loop中的MessageQueue佇列,這段程式碼宣告是這樣的
final MessageQueue mQueue;
final的宣告標示保證了獲取佇列的執行緒安全,我們繼續向下分析進入enqueueMessage這個方法中
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
可以看到這裡它呼叫了MessageQueue的enqueueMessage這個方法,重點來了
 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
可以看到enqueueMessage這個方法被自身的this鎖所保護,而MessageQueue在一個Handler為final標示,這兩個保護保證了Handler在多執行緒環境下使用sendMessage方法的執行緒安全性。

相關推薦

Android Handler 傳送訊息執行安全問題

Handler在多執行緒傳送訊息到訊息佇列時是否會產生執行緒安全問題。 下面對傳送流程進行分析 public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDel

Android Handler(子執行Handler)非同步訊息處理機制的妙用(活用訊號量) 建立強大的圖片載入類

最近建立了一個群,方便大家交流,群號:55032675 上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後

關於Android的UI非執行安全

1、我們都知道,在Android的開發中,非UI執行緒不能操作UI執行緒中的控制元件,即UI是非執行緒安全的;2、但是在工作執行緒(非UI執行緒)中呼叫ProgressBar控制元件的setProgress(int count)方法時,程式執行並    不會出現異常,3、但是

模擬Android Handler機制——單執行處理多工

訊息類(Message):package p; public class Message { private Runnable runnable; private long start; pr

淺談android執行安全handler處理

android的UI操作不是安全的,同時也只有主執行緒才能操作UI,同時主執行緒對UI操作有一定的時間限制(最長5秒)。為了能夠作一些比較好使的操作(比如下載、開啟大檔案等),android提供了一些列機制。 執行緒安全:如果你的程式碼所在的程序中又多個執行緒

Looper機制:主執行中利用handler向工作執行傳送訊息

注意:由主執行緒向非UI執行緒中傳送訊息的時候,非UI執行緒需要先新增訊息佇列,然後處理訊息迴圈。 (1).預設情況下android中新誕生的執行緒是沒有開啟訊息迴圈的。(主執行緒除外,主執行緒系統會自動為其建立Looper物件,開啟訊息迴圈。)

Android 裡面的 Handler 究竟是如何保證執行安全的?

關鍵在於handler操作的MessageQueue是執行緒安全的,請看MessageQueue的message入隊方法,看到synchronized關鍵字沒有,就是她了: final boole

Handler訊息傳遞機制(子執行中傳遞new Handler和主執行中new Handle傳遞訊息

> 子執行緒中更新UI new Thread(new Runnable() {         @Override         public void run() {             Looper.prepare();          

Android-多執行安全問題-synchronized

先看一個售票案例Demo,多執行緒程式對共享資料操作引發的安全問題: package android.java.thread09; /** * 售票執行緒 */ class Booking implements Runnable { /** * 模擬票的總算 10張票

消費RabbitMQ時的注意事項,如何禁止大量的訊息湧到Consumer,保證執行安全

按照官網提供的訂閱型寫法( Retrieving Messages By Subscription ("push API")) 我發現,RabbitMQ伺服器會在短時間內傳送大量的訊息給Consumer,然後,如果你沒有來得及Ack的話,那麼服務端會積壓大量的UnAcked訊息,而Cons

Android通訊模組(單執行,多執行通訊方式,Handler 與UI Thread的互動,Handler接合子執行的使用)

一丶概述 本週的學習計劃是Android通訊模組,內容:單執行緒,多執行緒通訊方式,Handler 與UI Thread的互動,Handler接合子執行緒的使用。 二丶效果演示(原始碼連結見文末) 三丶實現功能 1.演示使用Handler常見崩潰 2.handler更新

Android 開發之多執行處理——Handler 詳解

    Android開發過程中為什麼要多執行緒     我們建立的Service、Activity以及Broadcast均是一個主執行緒處理,這裡我們可以理解為UI執行緒。但是在操作一 些耗時操作時,比如I/O讀寫的大檔案讀寫,資料庫操作以及網路下載需要很長時間,為了不

Android執行安全問題總結

執行緒安全的定義 執行緒安全:如果你的程式碼所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的,或者說:一個類或者程式所提供的介面對於執

Android SQLite是執行安全的嗎?

我們操作資料庫一般使用ContentProvider,SQLiteOpenHelper,應用中使用SQLiteDatabase db = SQLiteOpenHelper.getReadableDatabase(),這個db需要呼叫db.close()或者openH

Android使用Handler實現子執行與子執行、主執行之間通訊

今天這篇文章只講一下怎麼使用Handler實現子執行緒與子執行緒之間、子執行緒與主執行緒之間如何進行通訊,關於具體的內部實現因為我也沒研究過,所以這篇文章講不了。 一、子執行緒向主執行緒傳值: 這個實現比較簡單,因為主執行緒自帶Looper機制,所有我們不用

Android之在一個類裡面註冊Handler傳送訊息在另外一個類裡面接收訊息

1、問題 我們要在一個類裡面變數或者函式變化需要改變另外一個類裡面的東西,這個時候java裡面除了介面回撥之外,我們還可以用註冊Handler來實現 2、程式碼實現 1、MainActivity

Android的程序與執行(3)執行安全問題

當一個程式啟動的時候,系統會為程式建立一個名為main的執行緒。這個執行緒重要性在於它負責把事件分發給適合的使用者元件,這些事件包括繪製事件。並且這個執行緒也是你的程式與Android UI工具包中的元件(比如android.widget和android.view包中的元件

Android之用Handler實現主執行和子執行互相通訊以及子執行和子執行之間的通訊

1、上程式碼 activity_main.xml檔案 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.

Android Studio——為什麼說android UI操作不是執行安全

可能在非UI執行緒中重新整理介面的時候,UI執行緒(或者其他非UI執行緒)也在重新整理介面,這樣就導致多個介面重新整理的操作不能同步,導致執行緒不安全。 1、為什麼說invalidate()不能直接線上程中呼叫? 2、它是怎麼違背單執行緒的? 3、android ui為

Android ContentProvider的執行安全(二)

框架層原理 從Provider使用方(Client App)通過getContentResolver()獲取到Provider的遠端物件,是一個三方的流程: (1)Client App向AMS獲取Provider遠端物件; (2)AMS會檢查對應的Prov