スレッドプライオリティ(優先度)を変更する
|Androidでスレッドの優先度を指定する方法を紹介します。Androidアプリケーションでは、UIスレッドで時間のかかる処理を行ってしまうと応答性に影響が出るのは周知の事実です。たとえば次のような処理はUIスレッドに適さないでしょう。
- アプリ外部:ネットワークやローカルファイル、データベース、ソケットへのアクセスする場合
- アプリ内部:ブロッキング(synchronized等)を利用したクリティカルセクションがある場合
- CPU時間:CPUを長く拘束する処理。たとえば画像処理のような時間がかかることがあらかじめ分かっている場合
さまざまな理由があってマルチスレッド化を検討すると思いますが、スレッドの優先度まで気にすることは稀です。それは上記で示した多くの例ではUIスレッドを守るため別スレッドに追い出す処理だから(=UIスレッドに比べて優先度が低いから)です。他のリソースに依存した待ち時間は優先度を高くしても効果が見込めません。
しかしながらVoIPの音声デコードやストリーム動画の受信などデータや処理に時間的な制約がある場合、スレッドの優先度を変える選択肢が取り得ます。その場合はスレッドを1つ作成し、ごく短い時間で処理を完了することをおすすめします。たくさんのスレッドをつかって細かく優先度を変えることは、制御の複雑化につながる可能性があります。
優先度を設定する
Androidではandroid.os.ProcessクラスのsetThreadPriorityメソッドを使えばスレッドの優先度を変更できます。
- android.os.Process.setThreadPriority (int tid, int priority)メソッド
- android.os.Process.setThreadPriority (int priority)メソッド
即値 | 定数 | 説明 |
---|---|---|
19 | THREAD_PRIORITY_LOWEST | 最も優先度が低いスレッドです。通常利用しません |
10 | THREAD_PRIORITY_BACKGROUND | バックグラウンド処理に最適な優先度です。デフォルトより低い優先度にすることで応答性への影響を最小限にしています |
1 | THREAD_PRIORITY_LESS_FAVORABLE | 標準的な優先度より、ほんの少し優先を下げた設定値です |
0 | THREAD_PRIORITY_DEFAULT | アプリのスレッドとして標準的な優先度です |
-1 | THREAD_PRIORITY_MORE_FAVORABLE | 標準的な優先度より、ほんの少し優先を上げた設定値です |
-2 | THREAD_PRIORITY_FOREGROUND | UIスレッドの設定値です。システムがUIスレッドを作る際に利用します。通常、アプリ開発者は利用しません |
-4 | THREAD_PRIORITY_DISPLAY | システムがUIを更新するために使う表示用スレッドの設定値です。通常、アプリ開発者は利用しません |
-8 | THREAD_PRIORITY_URGENT_DISPLAY | システムが画面描画やInputDevice情報を処理するための設定値です。非常に優先度が高いため、通常、アプリ開発者は使用しません |
-16 | THREAD_PRIORITY_AUDIO | オーディオ処理のための設定値です。アプリケーションは通常、この優先度に変更できません |
-19 | THREAD_PRIORITY_URGENT_AUDIO | オーディオ処理を最優先で行うための設定値です。アプリケーションは通常、この優先度に変更できません |
Linuxの優先度に準じており、優先度(nice値)は最も高い-20から最も低い19まで変更可能です。表からはUIスレッドを超える優先度を設定する場合は描画処理や音声処理など一部の用途が利用しているだけということがわかります。高い優先度をつけたい場合は、処理を分散できないか、ロジックの高速化して対応できないかなど十分に検討してください。
サンプルコードで優先度を指定したスレッドを作るThreadFactoryを見てみましょう。
■PriorityThreadFactory.java
public class PriorityThreadFactory implements ThreadFactory { private final int mPriority; private final AtomicInteger mNumber = new AtomicInteger(); private final String mName; public PriorityThreadFactory(String name, int priority) { mName = name; mPriority = priority; } @Override public Thread newThread(Runnable r) { return new Thread(r, mName + '-' + mNumber.getAndIncrement()) { @Override public void run() { // android.os.Processを使う場合 : Process.THREAD_PRIORITY_DEFAULT android.os.Process.setThreadPriority(mPriority); // java.lang.Threadを使う場合 : Thread.NORM_PRIORITY // this.setPriority( mPriority ); super.run(); } }; } }
PriorityThreadFactoryクラスのコンストラクタで受けとった優先度(mPriority)をandroid.os.Process.setThreadPriorityメソッドで指定しています。
サンプルでは参考までにjava.lang.Thread.setPriorityメソッドでの設定方法も紹介しています。この場合は定数値が異なりますがスレッドの優先度は次の通りです。
- java.lang.Thread.setPriority(int priority)メソッド
定数値 | 説明 |
---|---|
MIN_PRIORITY | android.os.Process.THREAD_PRIORITY_LOWEST同等(定数値は異なる) |
NORM_PRIORITY | android.os.Process.THREAD_PRIORITY_DEFAULT同等(定数値は異なる) |
MAX_PRIORITY | android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY同等(定数値は異なる) |
java.lang.Thread.setPriorityメソッドでも設定は可能ですが、表のとおり数が少ないため移植性等を考慮しなければandroid.os.Process.setThreadPriorityメソッドを優先すると良いでしょう(反対にjava.lang.Thread.setPriorityメソッドを使っているライブラリなど他環境から移植した場合でも、不具合が無ければandroid.os.Process.setThreadPriorityメソッドに置き換える必要はありません)。
以上、おつかれさまでした。