Androidメッセージキュー(3)--マルチスレッドとメッセージ処理


三,Androidメッセージキュー--マルチスレッドとメッセージ処理
原文の住所:http://www.e800.com.cn/articles/2011/0720/491429_2.shtml
AndroidシステムのLooperはスレッドのメッセージキューとメッセージループを管理しています。具体的にはLooperのソースコードを参照してください。現在のスレッドのLooperオブジェクトはLoop.myLooper()によって得られ、Loop.getMainLooper()によって現在のプロセスのメインスレッドのLooperオブジェクトが得られます。前に述べたAndroidシステムのメッセージ・キューとメッセージ・ループは、特定のスレッドに対してのみ存在することができ、(もちろん、存在しなくてもよい)メッセージ・キューとメッセージ・ループ(Looper)は、特定のスレッドのメッセージを本スレッドに配信することができ、スレッドをまたぐことができない。しかし、作成されたワークスレッドは、デフォルトではメッセージループとメッセージキューがありません。このスレッドがメッセージキューとメッセージループを有するようにするには、スレッド内で最初にLooper.prepare()を呼び出してメッセージキューを作成し、次にLooper.loop()を呼び出してメッセージループに入る必要があります。次の例に示します
class LooperThread extends Thread {

  public Handler mHandler;

  public void run() {

  Looper.prepare();

  mHandler = new Handler() {

  	public void handleMessage(Message msg) {

  	// process incoming messages here

  	}

  };

  	Looper.loop();

  }

}
このようにあなたのスレッドはメッセージ処理機構を持っています。Handlerでメッセージ処理を行います。
ActivityはUIスレッドであり、主スレッドで動作します。Androidシステムは起動時にActivityのためにメッセージ・キューとメッセージ・サイクルを作成します。詳細はActivityThread.javaファイルを参照してください。
Handlerの役割は、メッセージを特定のメッセージ・キューに追加し、メッセージ・キュー内のメッセージを配信して処理することである。Handlerを作成するときはループオブジェクトを指定し、指定しない場合は現在のスレッドのLooperで作成します。詳細な実装はロoperのソースコードを参照してください。
一つのActivityで複数のワークスレッドまたは他のコンポーネントが作成され、これらのスレッドまたはコンポーネントがActivityのメインスレッドメッセージキューに彼らのメッセージを入れると、このメッセージはメインスレッドで処理される。メインスレッドは一般にインタフェースの更新操作を担当しており、Androidシステムにおけるwegetはスレッドセキュリティではないので、このような方法はAndroidインターフェースの更新を良好に行うことができる。この方式はAndroidシステムで広く使われています。もう一つのスレッドはどうやってメッセージをメインスレッドのメッセージキューに入れますか?答えは、Handleオブジェクトを介して、HandlerオブジェクトがメインスレッドのLooperで作成される限り、HandlerのsendMessageなどのインターフェースを呼び出して、メッセージをキューに入れるのは、メインスレッドに入るメッセージ待ち行列です。そして、メッセージは、Handlerメインスレッドにおいて、handlerのhandleMessageインターフェースを呼び出して処理される。この中にスレッド同期の問題があります。まず以下の例を参考にして、Handlerオブジェクトのスレッドモデルを理解してください。
package com.simon;

  import android.app.Activity;

  import android.os.Bundle;

  import android.os.Message;

  import android.util.Log;

  import android.os.Handler;

  public class MyHandler extends Activity {

  	static final String TAG = "Handler";

  	Handler h = new Handler(){

  	public void handleMessage (Message msg)

  	{

  			switch(msg.what)

  		{

  			case HANDLER_TEST:
	
  			Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "
");    break;    }    } };    static final int HANDLER_TEST = 1;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "
");    new myThread().start();    setContentView(R.layout.main);    }    class myThread extends Thread    {    public void run()    {    Message msg = new Message();    msg.what = HANDLER_TEST;    h.sendMessage(msg);    Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "
");    }    }   }
この例では主に印刷であり,このような処理機構は各モジュールにおけるスレッドの状況である。以下は私のマシンの運転結果です。
09-10 23:40:51.478:DEBUG/Handler(302):The main thread id=1 09-10 23:40:51.569:DEBUG/Handler(302):The worker thread id=8 09-10 23:40:52 DEBUG/Handler(302):The handler=1
メッセージ処理はメインスレッドで処理されており、メッセージ処理関数では、リフレッシュインターフェースを含む主スレッド内の任意のリソースを安全に呼び出すことができることを示している。作業スレッドと主スレッドは異なるスレッドで動作しますので、この2つのスレッド間の競合関係に注意しなければなりません。
上記の例では、ワークスレッドにおいて、主スレッドhandlerオブジェクトにアクセスし、handlerを呼び出したオブジェクトがメッセージキューにメッセージを追加していることに気づくかもしれない。この過程でメッセージキューのデータが一致しない問題がありますか?答えはhandlerオブジェクトに問題がないということです。handlerオブジェクトが管理するLooperオブジェクトはスレッドが安全であるため、参加メッセージからメッセージキューへの参加やメッセージの読み出しは同期オブジェクト保護があります。具体的にはLooper.javaファイルを参照してください。上記の例では、handlerオブジェクトを修正していないので、handlerオブジェクトにデータが一致しない問題が発生する可能性はありません。
上記の分析を通して、次のような結論が得られます。
1、ワークスレッドを通して画面を更新する場合は、handlerオブジェクトの使用を推奨します。
2、ワークスレッドとメインスレッドの競合関係に注意する。handlerオブジェクトは、メインスレッドで作成されています(作業スレッドを起動した後は、修正しないでください。そうでないとデータが一致しません。)。そして、作業スレッドでは、安心してメッセージを送るためのSendMessageなどのインターフェースを呼び出すことができます。
3、2つのhanderオブジェクト以外の任意のプライマリスレッドのメンバ変数がワークスレッドで呼び出された場合、スレッド同期問題を慎重に考慮する。同期オブジェクトを追加して変数を保護する必要がある場合。
4、handlerオブジェクトのhandleMessageインターフェースはメインスレッドで呼び出されます。この関数では、任意の変数と関数をプライマリスレッドに呼び出すことができ、UIを更新するタスクが完了します。
5、Androidの多くのAPIもHandlerというスレッド特性を利用して、リベート関数のバリエーションとして使用者に通知しています。このように、Androidフレームは、スレッドにおいて、スレッド同期の問題を心配することなく、そのスレッドにメッセージを送ることができる。
Androidメッセージ処理機構を深く理解することは、アプリケーション開発にとって非常に重要であり、スレッド同期についてより深く認識することもできる。