プロセスとスレッドの概要

アプリ コンポーネントが起動し、アプリに他のコンポーネントがない場合 アプリケーション用の新しい Linux プロセスが、Android システムが 実行されます。デフォルトでは、同じアプリのすべてのコンポーネントが同じプロセスとスレッドで実行されますが、 メインスレッドと呼ばれます。

アプリケーション コンポーネントが起動し、プロセスがすでに存在する場合 そのアプリケーションの別のコンポーネントがすでに起動しており、そのコンポーネントは そのプロセス内で開始され、同じ実行スレッドを使用します。ただし、必要に応じて アプリケーション内の異なるコンポーネントを個別のプロセスで実行するほか、追加のコンポーネントを 必要があります。

このドキュメントでは、Android アプリでプロセスとスレッドがどのように機能するかについて説明します。

プロセス

デフォルトでは、アプリケーション コンポーネントはすべて同じプロセスで実行され、ほとんどのアプリケーションは 変更しないでください。ただし、特定のプロセスを制御する必要がある場合には、 含まれている場合は、マニフェスト ファイルで変更できます。

コンポーネント要素の各タイプのマニフェスト エントリ(<activity><service><receiver><provider>)は、android:process コンポーネントが実行されます。この属性を設定すると、各コンポーネントが プロセスを共有するコンポーネントもあれば、そうでないコンポーネントもあります。

また、 android:process: 異なるアプリのコンポーネントを同じリージョン内で実行可能 ただし、アプリケーションは同じ Linux ユーザー ID を共有し、 必要ありません。

<application> 要素は android:process 属性もサポートしています。この属性を使用して、 すべてのコンポーネントに適用されるデフォルト値。

Android は、リソースがシャットダウンされたとき、ある時点でプロセスをシャットダウンすることを決定することがあります。 より迅速にユーザーにサービスを提供する他のプロセスで必要とされます。アプリケーション その結果、シャットダウンされるプロセス内で実行されているコンポーネントは破棄されます。プロセスが開始される やり直す必要があるときは

シャットダウンするプロセスを決定する際、Android システムは、シャットダウンするプロセスの相対的な重要度を できます。たとえば、不要になったプロセスをホストしているプロセスをより簡単にシャットダウンできます。 目に見えるアクティビティをホストしているプロセスと比較します。使用するかどうかの判断は、 プロセスの終了は、そのプロセスで実行されているコンポーネントの状態によって異なります。

プロセスのライフサイクルと、プロセスのライフサイクルとアプリケーションの状態との関係については、 プロセスとアプリのライフサイクル

スレッド

アプリケーションが起動されると、システムはアプリケーションの実行スレッドを作成し、 メインスレッドといいます。このスレッドは、イベントをイベントにディスパッチする役割を担うため、非常に重要です。 描画イベントなどの適切なユーザー インターフェース ウィジェット。また、 ほとんどの場合、アプリがコンポーネントとやり取りするスレッド Android UI ツールキットの android.widget から android.view パッケージ。 このため、メインスレッドが UI スレッドと呼ばれます。ただし、特別な状況では、アプリのメイン UI スレッドではない可能性があります詳しくは、Thread アノテーション

システムがコンポーネントのインスタンスごとに個別のスレッドを作成することはありません。すべて 同じプロセスで実行されるコンポーネントは UI スレッドでインスタンス化され、 各コンポーネントはそのスレッドからディスパッチされます。そのため、システムに応答するメソッドが コールバック(onKeyDown() など) ライフサイクル コールバック メソッドをレポートするため、常にプロセスの UI スレッドで実行されます。

たとえば、ユーザーが画面上のボタンをタップすると、アプリの UI スレッドが タップイベントがウィジェットに送信されると、そのウィジェットが押された状態を設定し、無効化リクエストをウィジェットに送ります。 表示されます。UI スレッドがリクエストをキューから取り出し、ウィジェットに再描画を通知 できます。

アプリケーションを適切に実装しない限り、このシングル スレッド モデルでは、 ユーザーの操作に対する負荷の高い処理をアプリが行うと、パフォーマンスが低下する可能性があります。 UI スレッドでの長時間のオペレーション(ネットワーク アクセスや UI 全体をブロックしますスレッドがブロックされると、イベントをディスパッチできず、 描画イベントが含まれます。

ユーザーの視点から見ると、 アプリがハングしたように見えます。さらに悪いことに、UI スレッドが数秒以上ブロックされると、 ユーザーには「 対応中」(ANR)のダイアログが表示されます。ユーザーはその後、アプリケーションを終了したり、アンインストールしたりするかもしれません できます。

Android UI ツールキットはスレッドセーフではありません。そのため 作成する方法も学習しましたUI からユーザー インターフェースに対するすべての操作を行う 使用します。Android のシングルスレッド モデルには、次の 2 つのルールがあります。

  1. UI スレッドをブロックしない。
  2. UI スレッドの外部から Android UI ツールキットにアクセスしないでください。

ワーカー スレッド

このシングル スレッド モデルであるため、アプリの応答性に UI スレッドをブロックしないものにする必要があります。なんらかの操作を すぐに実行できない場合は、別のバックグラウンドまたは ワーカー スレッドのことです。UI は、それ以外のスレッドからは更新できない 呼び出します。

こうしたルールを遵守できるように、Android には、他のアプリから UI スレッドにアクセスする方法がいくつか用意されています。 説明します。以下に、有用な方法の一覧を示します。

次の例では、View.post(Runnable) を使用しています。

Kotlin

fun onClick(v: View) {
    Thread(Runnable {
        // A potentially time consuming task.
        val bitmap = processBitMap("image.png")
        imageView.post {
            imageView.setImageBitmap(bitmap)
        }
    }).start()
}

Java

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // A potentially time consuming task.
            final Bitmap bitmap =
                    processBitMap("image.png");
            imageView.post(new Runnable() {
                public void run() {
                    imageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

バックグラウンド処理は別のスレッドから行われるため、この実装はスレッドセーフです。 ImageView は常に UI スレッドから操作されます。

しかし、操作が複雑になるにつれ、この種のコードは複雑になり、 メンテナンスが困難です。ワーカー スレッドとのより複雑なインタラクションを処理するには、 ワーカー スレッドで Handler を使用する UI スレッドから配信されたメッセージを処理できます。P-MAX キャンペーンの バックグラウンド スレッドの処理をスケジュールし、UI スレッドと通信します。詳しくは、 バックグラウンド処理の概要

スレッドセーフ メソッド

状況によっては、実装したメソッドが複数のスレッドから呼び出され、 スレッドセーフとして作成する必要があります。

これは主に、バインドされたサービス内のメソッドなど、リモートで呼び出すことができるメソッドに当てはまります。通話中の IBinder に実装されたメソッドは、 IBinder が実行されている場合、メソッドは呼び出し元のスレッドで実行されます。 ただし、別のプロセスからの呼び出しの場合、メソッドは システムが IBinder と同じプロセスで維持するスレッドのプール。 プロセスの UI スレッドでは実行されません。

たとえば、Service の onBind() メソッドが、サービスの UI スレッドから呼び出される サービスのプロセス、onBind() が返すオブジェクトに実装されているメソッド( リモート プロシージャ コール(RPC)メソッドを実装するサブクラスで、 表示されます。1 つのサービスが複数のクライアントを持つことができるため、複数のプールスレッドが関与可能 同時に同じ IBinder メソッドを実行するため、IBinder メソッドは スレッドセーフとして実装されます。

同様に、コンテンツ プロバイダは、他のプロセスで発生したデータ リクエストを受信できます。 ContentResolverContentProvider クラスはプロセス間通信(IPC)の管理方法の詳細を非表示にします。 ただし、これらのリクエストに応答する ContentProvider メソッド( query(), insert(), delete(), update(), および getType() は、 UI ではなく、コンテンツ プロバイダのプロセスのスレッドのプールから呼び出される 呼び出します。これらのメソッドは、同じディレクトリ内の任意の数のスレッドから呼び出される可能性があるため、 同時に、それらもスレッドセーフになるように実装する必要があります。

プロセス間通信(IPC)

Android には、RPC を使用して IPC を行うメカニズムがあります。このメカニズムでは、アクティビティまたは他のアプリからメソッドが呼び出されます。 別のプロセスでリモート実行され、すべての結果がシステムに返されます。 呼び出します。そのためには、メソッド呼び出しとそのデータを、オペレーティング システムが処理できるレベルまで分解する必要があります。 その情報をローカル プロセスおよびアドレス空間からリモート プロセスに送信し、 呼び出しを再構成して再現します

戻り値は 逆方向に伝送されることもあります。Android には、これらの IPC を実行するためのコードがすべて用意されています。 そのため、RPC プログラミング インターフェースの定義と実装に集中できます。

IPC を実行するには、bindService() を使用してアプリケーションをサービスにバインドする必要があります。詳細については、Service の概要をご覧ください。