Android/javaマルチスレッド(一)-threadの使用とソースコード分析
6657 ワード
スレッドの概念とステータス
スレッドを学習する前に、各プログラムの実行には親プロセスがあり、私たちのスレッドはこの親プロセスで実行されます.Androidでは、デフォルトでは、すべてのコンポーネントプログラムが同じプロセスで実行され、実行スレッドが作成されます.このプロセスでは、通称「メインスレッド」と呼ばれています.このスレッドで時間のかかる操作をしてプログラムカートンを作成した場合、「スレッドブロック」と呼ばれます.この場合、別のスレッドを作成して時間のかかる操作を実行する必要があります.
スレッド内のメソッドの使用を理解するには、スレッドの実行状態を理解する必要があります.スレッドの作成から実行まで、合計6つのステータスがあります. NEW(スレッド作成未起動) RUNNABLE(実行中のスレッド) BLOCKED(ブロックされ、モニタロックの解放を待つ) . WAITING(起動待ち) TIMED_WAITING(待機または一定時間の睡眠が覚醒) TERMINTED(スレッド終了、消滅) これらの状態は
このうち
もちろん,両者の応用はスレッドだけでなく,必要なメソッド呼び出しにも用いられる.
スレッドのソースコードおよびメソッドの使用
ThreadはRunnableインタフェースを実装し、いくつかのスレッドでよく使用される変数を宣言しました. groupスレッドグループ、スレッドグループは他のスレッドグループを含み、ツリー構造を形成している.初期のスレッドグループを除いて、他のスレッドグループには親プロセスがあり、スレッドは現在のスレッドグループの情報にアクセスできるが、親スレッドグループの情報 にアクセスできない. daemonはデーモンスレッドかどうか、デーモンスレッドとは何か、デーモンスレッドはそのスレッドを作成することに依存するスレッドの一種であり、一般的なスレッドとは異なり、そのスレッドを作成して閉じると閉じられるが、一般的なスレッドではなく、私たちのゴミ収集器スレッドのようにデーモンスレッド である. threadInitNumber現在のスレッドの識別子であり、スレッドの作成順序に従って重畳された である. nameスレッドの名前は、指定されていなければ と命名される. priorityスレッド優先度は、3つの状態 に対応する. stackSizeスタックサイズ target現在のターゲットスレッド contextClassLoaderクラスローダは、このスレッドの情報を保存するためのものであり、ブレークポイント再送などの機能は に使用することができる. uncaughtHandlerスレッドは例外呼び出しクラスをキャプチャしていません.設定していない場合は、デフォルトで をキャプチャできます.
いくつかの一般的な変数を理解した後、いくつかの一般的な方法を見てみましょう.
start()メソッド
スレッドを起動するには、このメソッドを呼び出すだけで、スレッドが新たに開き、必要なリソースに割り当てられます.Threadの構造方法を見てみると、最終的には
したがって、新しいスレッドを作成してもリソースは消費されず、star後にのみ必要なリソースが割り当てられます.このとき、スレッド状態は
run()メソッド
このメソッドはスレッドで実行される論理を処理するために使用され、Threadクラスを継承する場合はメソッドを書き換える必要があります.
sleep()メソッド
スレッドをしばらくスリープさせることは、スレッドをブロック状態にすることに相当します.スレッドがスリープしてもロックメカニズムが有効であっても、他のスレッドはオブジェクトロックが解放されるまでロックされたデータ構造にアクセスできません.このとき、スレッド状態は
yield()メソッド
現在のスレッドに対応する権限を与え,他のスレッドに譲歩させることは,CPUの過度な使用を防止する有効な手段である.効果は
join()メソッド
この方法は、スレッドを優先して実行することです.残りのスレッドは、スレッドが実行されるまで停止します.スレッドを正常に走行している車両(オンラインキュー)と見なすことができます.そのうちの1台にjoin(カーブオーバー)を使用すると、残りの車は行を譲り(スレッドは一時停止状態に入ります)、優先的に走行させ(joinのスレッドが運行します)、終点に達するまで(運行が完了します)、走行を続けます(実行を続けます)
interrupt()メソッド
スレッドを中断すると,スレッドがrunメソッドを実行した論理が終了状態に入ることが分かった.このメソッドを呼び出すと、ブロックされたスレッドが
実行が完了したかどうかを制御してスレッドを終了する変数を設定できます.スレッド状態は
スレッドを学習する前に、各プログラムの実行には親プロセスがあり、私たちのスレッドはこの親プロセスで実行されます.Androidでは、デフォルトでは、すべてのコンポーネントプログラムが同じプロセスで実行され、実行スレッドが作成されます.このプロセスでは、通称「メインスレッド」と呼ばれています.このスレッドで時間のかかる操作をしてプログラムカートンを作成した場合、「スレッドブロック」と呼ばれます.この場合、別のスレッドを作成して時間のかかる操作を実行する必要があります.
スレッド内のメソッドの使用を理解するには、スレッドの実行状態を理解する必要があります.スレッドの作成から実行まで、合計6つのステータスがあります.
Thread
のソースコードのState
の列挙に対応し、getState()
の方法によってスレッドの実行状態を取得することができる.このうち
BLOCKED
はモニタロックを待つプロセスを示しているが、モニタロックとは何か、モニタロックはスレッドの不安全を解決するために誕生した方法であり、複数のプロセスが1つのデータ構造を同時に操作して修正すると、データ構造が不確定になり、「スレッドが不安全」と呼ぶ.そこで、synchronized( )
やlock
などのメカニズムを使用して、このスレッドが安全ではないことを解決し、このロックを装着すると、現在1つのスレッドだけがこのデータ構造を修正することができ、他のスレッドは待つ必要があります.これはデータ構造の一致性を保証し、他のスレッドは待機状態、つまり私たちのBLOCKED
状態に入ります.synchronized
の使用例: class MyThread extends Thread {
@Override
public void run() {
synchronized (this) {
//
}
}
}
lock
の使用例: class MyThread extends Thread {
private final ReentrantLock lock = new ReentrantLock ();
@Override
public void run() {
lock.lock();
//
lock.unlock();
}
}
もちろん,両者の応用はスレッドだけでなく,必要なメソッド呼び出しにも用いられる.
スレッドのソースコードおよびメソッドの使用
Thread
ソース:public class Thread implements Runnable {
...........
/* Some of these are accessed directly by the VM; do not rename them. */
private volatile long nativePeer;
volatile ThreadGroup group;
volatile boolean daemon;
volatile String name;
volatile int priority;
volatile long stackSize;
Runnable target;
private static int count = 0;
private long threadInitNumber ;
/**
* Normal thread local values.
*/
ThreadLocal.Values localValues;
/**
* Inheritable thread local values.
*/
ThreadLocal.Values inheritableValues;
/** Callbacks to run on interruption. */
private final List interruptActions = new ArrayList();
/**
* Holds the class loader for this Thread, in case there is one.
*/
private ClassLoader contextClassLoader;
/**
* Holds the handler for uncaught exceptions in this Thread,
* in case there is one.
*/
private UncaughtExceptionHandler uncaughtHandler;
/**
* Holds the default handler for uncaught exceptions, in case there is one.
*/
private static UncaughtExceptionHandler defaultUncaughtHandler;
.....
}
ThreadはRunnableインタフェースを実装し、いくつかのスレッドでよく使用される変数を宣言しました.
"Thread-" + threadInitNumber
の論理でMIN_PRIORITY
、NORM_PRIORITY
、MAX_PRIORITY
があり、それぞれ低、中、高defaultUncaughtHandler
を使用して例外を処理します.メインスレッドもThreadなので、UncaughtExceptionHandler
インタフェースを実装し、Thread.setDefaultUncaughtExceptionHandler()
メソッドを呼び出すことで、カスタム例外取得クラスをThreadに設定することができます.これにより、グローバルな例外いくつかの一般的な変数を理解した後、いくつかの一般的な方法を見てみましょう.
start()メソッド
スレッドを起動するには、このメソッドを呼び出すだけで、スレッドが新たに開き、必要なリソースに割り当てられます.Threadの構造方法を見てみると、最終的には
init
メソッドが呼び出され、基本変数を初期化するだけで、リソースに割り当てられていないことがわかりました. private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
Thread parent = currentThread();
if (g == null) {
g = parent.getThreadGroup();
}
g.addUnstarted();
this.group = g;
this.target = target;
this.priority = parent.getPriority();
this.daemon = parent.isDaemon();
setName(name);
init2(parent);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
tid = nextThreadID();
}
したがって、新しいスレッドを作成してもリソースは消費されず、star後にのみ必要なリソースが割り当てられます.このとき、スレッド状態は
NEW
からRUNNABLE
に変わります.run()メソッド
このメソッドはスレッドで実行される論理を処理するために使用され、Threadクラスを継承する場合はメソッドを書き換える必要があります.
sleep()メソッド
sleep(long millis) //
sleep(long millis,int nanoseconds) // ,
スレッドをしばらくスリープさせることは、スレッドをブロック状態にすることに相当します.スレッドがスリープしてもロックメカニズムが有効であっても、他のスレッドはオブジェクトロックが解放されるまでロックされたデータ構造にアクセスできません.このとき、スレッド状態は
RUNNABLE
からTIMED_WAITING
に入ります.yield()メソッド
現在のスレッドに対応する権限を与え,他のスレッドに譲歩させることは,CPUの過度な使用を防止する有効な手段である.効果は
sleep
とさほど差はないが、具体的な時間を指定することができず、スレッドをブロック状態にするのではなく、準備完了状態にする.このときスレッド状態はRUNNABLE
からWAITING
に入る.join()メソッド
join()
join(long millis) //
join(long millis,int nanoseconds) // ,
この方法は、スレッドを優先して実行することです.残りのスレッドは、スレッドが実行されるまで停止します.スレッドを正常に走行している車両(オンラインキュー)と見なすことができます.そのうちの1台にjoin(カーブオーバー)を使用すると、残りの車は行を譲り(スレッドは一時停止状態に入ります)、優先的に走行させ(joinのスレッドが運行します)、終点に達するまで(運行が完了します)、走行を続けます(実行を続けます)
join
ソースコードでは呼び出されたwait()
メソッドであり、wait()
メソッドはスレッドをブロック状態にしてオブジェクトロックを解放することができるので、join
メソッドもオブジェクトロックを解放することができるinterrupt()メソッド
スレッドを中断すると,スレッドがrunメソッドを実行した論理が終了状態に入ることが分かった.このメソッドを呼び出すと、ブロックされたスレッドが
InterruptedException
の異常を放出し、スレッドを終了します.isInterrupted()
を呼び出すと、スレッドが終了したかどうかを判断できますが、ブロックされていないスレッドがどのように中断されるかを確認します.class MyThread extends Thread{
private volatile boolean isStop = false;
@Override
public void run() {
int i = 0;
while(!isStop){
i++;
}
}
public void setStop(boolean stop){
this.isStop = stop;
}
}
実行が完了したかどうかを制御してスレッドを終了する変数を設定できます.スレッド状態は
TERMINATED
状態に入ります.