JAvaはどのように優雅に原生のThreadスレッドを停止します
8078 ワード
最近は、プロジェクトでフレームアニメーションが使用されているためです.よく知られているように、フレームアニメーションはリソースを消費し、一度関連するピクチャが多いと、OOMが容易になります.
そこでこの問題を解決するために,Surface Viewをカスタマイズし,サブスレッドを用いてフレームごとにbitmapを描画する方式を採用した.このSurfaceで再生する画像リストは設定可能です.つまり、前のアニメーションがまだ放送されていないかもしれないので、新しい画像リストを設定しました.これにより、古いアニメーションスレッドを停止し、新しいスレッドを開いて新しいアニメーションを再生する必要があります.そこでタイトルのこの問題に関連しました:javaはどのように優雅に原生のThreadスレッドを停止します.
Threadクラスには、スレッドを停止するためのstopメソッドがあることはよく知られています.では、この方法を直接使ってもいいですか?答えはだめです.stop方法はすでに公式に明確に廃棄されているからだ.主な原因は、この方法があまりにも簡単で乱暴だからだ.少なくとも以下の問題が発生します.
(1)stop法はスレッド操作の原子性を破壊する.たとえば、スレッドの操作には同期が必要です.後でいくつかの重要な方法が実行されるか、リソースを解放しなければならない可能性があります.このときstopメソッドを呼び出してスレッドを停止し、彼は何が同期しているかどうかにかかわらず、このプロセスが完全に完了しているかどうかを確認します.直接止めてあげます.
以上の理由からstopメソッドを呼び出すと、UnsupportedOperationExceptionの例外が直接受信されます.
stopメソッドが使えない以上.他に何かできる方法はありませんか?友達がThread類の中にinterruptの方法があることを覚えていて、interruptは中断ではありませんか?では、私はこの方法を呼び出せばいいのではないでしょうか.
ここではまず3つの明確な結論を直接出しましょう.
(1)この方法の名前には迷いがある.
(2)この方法は実際には1つのスレッドを停止することはできない.
(3)我々が書いたスレッドがこの方法で停止した場合があるが,そうではなく,このスレッドを停止した根本的な原因は異常である.
次の2つの例を示します.
(1)
まずstartThreadメソッドを呼び出してスレッドを開き、スレッドがしばらく走るのを待っています.その後interruptThreadメソッドを呼び出します.ログを見てみましょう
スレッドが止まったんじゃないの?そしてfinallyで呼び出さなければならないコードmustDoThingsメソッドも正常に呼び出されました.しかし、もっとよく見ると、finallyの前にInterruptedExceptionが投げ出されていることがわかります.だから、今回のスレッドの停止とmustDoThingsメソッドの呼び出しは完全にこの異常のためです.
私たちはまずstartThread、それからinterruptThreadです.今回どのようにinterruptThreadメソッドを呼び出しても、このスレッドを止めることはできません.
実はinterruptメソッドは、スレッドを停止する識別ビットを設定するだけです.スレッドがブロックされている場合、interruptメソッドを呼び出すとInterruptException異常が放出され、停止スレッドの識別ビットが消去されます.
stopが使えないことを知った以上、interruptメソッドはスレッドを直接停止することはできません.スレッドを停止する正しい姿勢は何ですか?ここでは、一般的な2つを提供します.
(1)停止スレッドの識別ビットの自己保守
(2)interruptメソッドで設定した識別ビット
Threadが識別ビットの設定を提供する以上,この方法を用いて実現することができる.Threadはまた、この識別ビットを取得するためのisInterruptedメソッドを提供する.
try-catchの小包範囲の問題に注意してください.前に述べたように、ブロックされたスレッドに対してinterruptメソッドを呼び出すと、スレッドを停止する識別ビットが消去され、この識別ビットがfalseになるからです.以下のコードを書いたらinterruptメソッドではこのスレッドを止められません.
エラーのデモ:
そこでこの問題を解決するために,Surface Viewをカスタマイズし,サブスレッドを用いてフレームごとにbitmapを描画する方式を採用した.このSurfaceで再生する画像リストは設定可能です.つまり、前のアニメーションがまだ放送されていないかもしれないので、新しい画像リストを設定しました.これにより、古いアニメーションスレッドを停止し、新しいスレッドを開いて新しいアニメーションを再生する必要があります.そこでタイトルのこの問題に関連しました:javaはどのように優雅に原生のThreadスレッドを停止します.
Threadクラスには、スレッドを停止するためのstopメソッドがあることはよく知られています.では、この方法を直接使ってもいいですか?答えはだめです.stop方法はすでに公式に明確に廃棄されているからだ.主な原因は、この方法があまりにも簡単で乱暴だからだ.少なくとも以下の問題が発生します.
(1)stop法はスレッド操作の原子性を破壊する.たとえば、スレッドの操作には同期が必要です.後でいくつかの重要な方法が実行されるか、リソースを解放しなければならない可能性があります.このときstopメソッドを呼び出してスレッドを停止し、彼は何が同期しているかどうかにかかわらず、このプロセスが完全に完了しているかどうかを確認します.直接止めてあげます.
以上の理由からstopメソッドを呼び出すと、UnsupportedOperationExceptionの例外が直接受信されます.
stopメソッドが使えない以上.他に何かできる方法はありませんか?友達がThread類の中にinterruptの方法があることを覚えていて、interruptは中断ではありませんか?では、私はこの方法を呼び出せばいいのではないでしょうか.
ここではまず3つの明確な結論を直接出しましょう.
(1)この方法の名前には迷いがある.
(2)この方法は実際には1つのスレッドを停止することはできない.
(3)我々が書いたスレッドがこの方法で停止した場合があるが,そうではなく,このスレッドを停止した根本的な原因は異常である.
次の2つの例を示します.
(1)
private Thread mThread;
private boolean mIsRunning = true;
private void startThread(){
mThread = new Thread(
new Runnable() {
@Override
public void run() {
int i = 0;
try {
while(mIsRunning) {
Log.d(
"MyThreadDemo",
String.valueOf(i)
);
mThread.sleep(1000);
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
mustDoThings();
}
}
}
);
mThread.start();
}
private void interruptThread(){
if(mThread!=null){
mThread.interrupt();
}
}
private void mustDoThings(){
Log.d("MyThreadDemo"," ");
}
まずstartThreadメソッドを呼び出してスレッドを開き、スレッドがしばらく走るのを待っています.その後interruptThreadメソッドを呼び出します.ログを見てみましょう
06-27 17:56:18.762 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 4
06-27 17:56:19.763 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 5
06-27 17:56:20.764 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 6
06-27 17:56:21.764 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 7
06-27 17:56:22.765 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 8
06-27 17:56:23.766 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 9
06-27 17:56:24.766 2480-2935/com.wm.mythreaddemo D/MyThreadDemo: 10
06-27 17:56:25.433 2480-2935/com.wm.mythreaddemo W/System.err: java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
06-27 17:56:25.434 2480-2935/com.wm.mythreaddemo W/System.err: at java.lang.Thread.sleep(Thread.java:1031)
at java.lang.Thread.sleep(Thread.java:985)
at com.wm.mythreaddemo.MainActivity$1.run(MainActivity.java:74)
at java.lang.Thread.run(Thread.java:818)
06-27 17:56:25.434 2480-2935/com.wm.mythreaddemo D/MyThreadDemo:
スレッドが止まったんじゃないの?そしてfinallyで呼び出さなければならないコードmustDoThingsメソッドも正常に呼び出されました.しかし、もっとよく見ると、finallyの前にInterruptedExceptionが投げ出されていることがわかります.だから、今回のスレッドの停止とmustDoThingsメソッドの呼び出しは完全にこの異常のためです.
private Thread mThread;
private boolean mIsRunning = true;
private void startThread(){
mThread = new Thread(
new Runnable() {
@Override
public void run() {
int i = 0;
while(mIsRunning) {
Log.d(
"MyThreadDemo",
String.valueOf(i)
);
i++;
}
}
}
);
mThread.start();
}
private void interruptThread(){
if(mThread!=null){
mThread.interrupt();
}
}
私たちはまずstartThread、それからinterruptThreadです.今回どのようにinterruptThreadメソッドを呼び出しても、このスレッドを止めることはできません.
実はinterruptメソッドは、スレッドを停止する識別ビットを設定するだけです.スレッドがブロックされている場合、interruptメソッドを呼び出すとInterruptException異常が放出され、停止スレッドの識別ビットが消去されます.
stopが使えないことを知った以上、interruptメソッドはスレッドを直接停止することはできません.スレッドを停止する正しい姿勢は何ですか?ここでは、一般的な2つを提供します.
(1)停止スレッドの識別ビットの自己保守
private Thread mThread;
private boolean mIsRunning = true;
private void startThread(){
mThread = new Thread(
new Runnable() {
@Override
public void run() {
int i = 0;
while(mIsRunning){
Log.d(
"MyThreadDemo",
String.valueOf(i)
);
try {
mThread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
mustDoThings();
}
}
);
mThread.start();
}
private void stopBoolThread(){
mIsRunning = false;
}
private void mustDoThings(){
Log.d("MyThreadDemo"," ");
}
これは、whileループが実行を継続する必要があるかどうかを制御するために、識別ビットを完全に自分で維持することである.続行しない場合は、whileの後に必要な操作の処理を行います.(2)interruptメソッドで設定した識別ビット
Threadが識別ビットの設定を提供する以上,この方法を用いて実現することができる.Threadはまた、この識別ビットを取得するためのisInterruptedメソッドを提供する.
private Thread mThread;
private void startThread(){
mThread = new Thread(
new Runnable() {
@Override
public void run() {
int i = 0;
try {
while(!mThread.isInterrupted()){
Log.d(
"MyThreadDemo",
String.valueOf(i)
);
mThread.sleep(1000);
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mustDoThings();
}
}
}
);
mThread.start();
}
private void interruptThread(){
if(mThread!=null){
mThread.interrupt();
}
}
try-catchの小包範囲の問題に注意してください.前に述べたように、ブロックされたスレッドに対してinterruptメソッドを呼び出すと、スレッドを停止する識別ビットが消去され、この識別ビットがfalseになるからです.以下のコードを書いたらinterruptメソッドではこのスレッドを止められません.
エラーのデモ:
private void startThread(){
mThread = new Thread(
new Runnable() {
@Override
public void run() {
int i = 0;
while(!mThread.isInterrupted()){
Log.d(
"MyThreadDemo",
String.valueOf(i)
);
try {
mThread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
mustDoThings();
}
}
);
mThread.start();
}