Javaスレッド割り込みisAliveVolatile

1.1概要

  1. Java割り込みどのように実装されているかを理解する
  2. 例外と何か、およびそれらを
    割り込みで使用する方法を理解する
  3. スレッド終了する方法を理解する
  4. スレッドリスクいくつかとそれらを軽減する方法を理解する

1.2スレッドとして自分自身への参照を取得する

Thread.currentThread().interrupt();

1.3メソッドの要約

Thread.sleep(1000)

  • スレッドの実行を1000ミリ秒一時停止します

myThread.join()
結合機能の解釈

  • myThreadの実行が完了するまで、現在のスレッドを一時停止します
  • つまり、myThreadのrun()メソッドが終了しました
    。スレッドAのrunメソッドは、スレッドBの結合を呼び出します。このとき、スレッドAはブロック状態です。スレッドAは、スレッドBが終了するか終了するまで実行を継続しません。

myThread.interrupt()

  • myThreadに割り込み信号を送信する
  • これにより、myThreadの割り込みフラグがtrueに設定されます

2.1割り込みとは

  1. 割り込みは、スレッドが実行していることを停止し、それ以外のことを実行する必要があることをスレッドに示します。
  2. プログラマーは、スレッドが割り込みにどのように応答するかを決定します
  3. スレッドは、割り込み対象のスレッドオブジェクトでinterrupt()を呼び出す割り込みを送信します。
  4. 割り込みメカニズムが正しく機能するには、割り込みスレッドがそれをサポートしている必要があります。(割り込みフラグを確認してください)

2.2割り込みメカニズム

  1. 割り込みメカニズムは、割り込みステータスと呼ばれる内部フラグを使用して実装されます。
  2. ターゲットスレッドで割り込みを呼び出すと、このフラグが設定されます
  3. スレッドは、静的メソッドThread.interrupted()を呼び出すことにより、割り込みをチェックできます。
  4. あるスレッドは、非静的isInterrupted()を使用して、別のスレッドの割り込みステータスを照会できます。

2.32つの割り込み方法

  • Thread.interrupted()静的であり、現在のスレッドの割り込みフラグがtrueに設定されているかどうかを確認します。
    • 呼び出されたスレッドに対してのみ機能します
    • その後、割り込みステータスは自動的にクリアされます
  • mythread.isInterrupted()呼び出されたThreadオブジェクトをチェックするインスタンスメソッドです。
    • 別のスレッドが中断されているかどうかを確認するために使用できます
    • 例:if(thread2.isInterrupted()== true)…
  • 一般的なエラーは、これら2つを混同することです

2.4割り込みフラグを確認する

MyThread myThread = new MyThread()
if (myThread.isInterrupted())
{
    
    } //Correct syntax
//Example 1
//Doesn’t check the interrupt flag! Just ignores it!
class MyThread extends Thread
{
    
    
    public void run(){
    
    
        for(int i =1;i <=5;i++){
    
    
            System.out.println(i);
        }
    }

    public static void main(String args[]){
    
    
    MyThread t1 = new MyThread();
    t1.start();
    t1.interrupt();
    }
}

??? リマインダー:出口を直接投げる

try{
    
    ...}
catch (FileNotFoundException e){
    
    
    System.err.println("FileNotFoundException:" + e.getMessage());
    throw new SampleException(e);
}
catch (IOException e){
    
    
    System.err.println("Caught IOException:" + e.getMessage());
}

2.5 InterruptedException

//Example2 Interrupting a thread that stops working
class MyThread extends Thread{
    
    
    public void run(){
    
    
        try{
    
    
            Thread.sleep(1000);
            System.out.println("Finished!"); //Not printed
        }
        catch(InterruptedException e ){
    
    
            //This doesn't really do anything
            System.out.println("I'm interrupted"); //Printed
            System.exit(-1);
            //This should be used to deal with the exception

        }
    }

    public static void main (String args[]){
    
    
        MyThread t1 = new MyThread();
        t1.start();
        try{
    
    
            t1.interrupt();//Wrong Syntax
        }
        catch(Exception e)
        {
    
    
            System.out.println("Exception handled" +e);
        }
    }
}
  • スレッドがスリープしているか、別のスレッドに参加または待機している場合:

      1. InterruptedExceptionがスローされます
      1. 中断されたステータスはクリアされ
        ますスレッドを片付けて終了するために何かをします
  • 中断されたステータスの復元

public void run(){
    
     
    while(!Thread.currentThread().isInterrupted())
    {
    
    
        // Doing some heavy operations
        try {
    
    
        Thread.sleep(5000);
        }
        catch(InterruptedException e)
        {
    
    
        Thread.currentThread().interrupt();
        //interrupt again as may need to do something rather than just exit
        }
    }
}

3.スレッドの終了

3.1 isAlive()

  1. スレッドは、が開始されてもまだ終了していない場合、生きていると言われます(isAlive()はtrueを返します)
  2. isAlive()メソッドは、(呼び出された)スレッドがまだ実行中であり、終了していない場合にtrueを返します
  3. Threadクラスが付属していますインスタンスメソッドのスレッドがであるかどうかを判断するためのisAlive()生まれの状態または死んだ()を返すのisAliveを呼び出している状態はfalse
if(myThread.isAlive())
{
    
    
    //check something  
    //myThread.interrupt();
}

スレッドが終了するのを待つために一般的に使用するメソッドは、join()と呼ばれます。

3.2スレッドを終了する(3つの方法の概要)

スレッドを強制的に停止するコマンドはありません(Javaの場合)

  1. スレッドは終了し、自然に終了します
  2. スレッドはデーモン(后台程序)スレッドとしてマークされていますこのスレッドを作成した親スレッドが終了すると、このhreadは強制的に(有力地)終了します。
  3. スレッドは、作業中に割り込み信号を受信しました
  • 作業を続行しないことを決定し、run()メソッドを終了します。
  • また、信号を無視して作業を続行することもできます。

3.3スレッドを自然に仕上げます

  • または、共有ブール値を使用することもできます(例:pleaseFinish)
    • pleaseFinishがtrueに設定されているかどうかを定期的に確認してください
    • trueの場合、スレッドを
      揮発性に終了します—揮発性
class MyThread extends Thread{
    
    
    private volatile boolean pleaseFinish = false;

    public void run(){
    
    
        //Periodically check for pleaseFinish to be  
        //set to true

        //Do something  
        //Finish nturally  
    }
    public void finishThreadPlease(){
    
    
        pleaseFinish = true;
        /*Be careful when using pleaseFinish  

        If thread is in a non-runnable state, setting a stpo flag variable will have no effect
        
        A thread is in a non-runnale state if  
        + Its sleep method is invoked.
        + The thread calls the wait method to wait for a specific condition to be satisfied.  
        + The thread is blocking on I/O

        */
    }
}

3.4デーモンスレッド

  • 起動してからデーモン化することはできません。
  • myThread.setDaemon(false)
    ワーカースレッド、親スレッドが終了した後実行を継続します。

  • myThread.setDaemon(true)親スレッドが終了すると、
    ワーカースレッドが終了します。

public void run(){
    
    
    WorkerThread t1 = new WorkerThread();
    t1.setDaemon(true);
    t1.start();
    //do sth  
    //this thread completes
    //When this thread completes:
    //t1 will also be terminated(automatically)
}

3.5スレッドを中断する

InterruptedExceptionをキャッチしてから、スレッドを停止する必要があります

public void run()
{
    
    
    for (int i = 0; i < importantInfo.length; i++)
    {
    
    
        try {
    
     Thread.sleep(4000); }
        catch (InterruptedException e)
        {
    
    return; }
    System.out.println(importantInfo[i]);
    }
}

安全に停止してクリーンアップできる戦略的なポイントで、割り込みを定期的にチェックします

if (Thread.currentThread.isInterrupted())
{
    
    // cleanup and stop execution
return;
}
public class InterruptThread {
    
    
public static void main(String[] args) {
    
    
Thread thread1 = new Thread(new WaitRunnable());
thread1.start();
try {
    
     Thread.sleep(1000); } // wait a second to make sure thread1 started
catch (InterruptedException e) {
    
     e.printStackTrace(); }
thread1.interrupt(); } // now interrupt thread1

中断されたステータスがfalseに設定されている例。

private static class WaitRunnable implements Runnable {
    
    
@Override
public void run() {
    
    
System.out.println("Current time millis : " + System.currentTimeMillis());
try {
    
     Thread.sleep(5000); } // will be asleep when interrupt comes
catch (InterruptedException e) {
    
    
System.out.println("The thread has been interrupted");

System.out.println("The thread is interrupted : " + Thread.interrupted(); // the interrupted status has been set to false}

System.out.println("Current time millis :+ System.currentTimeMillis()); } } }

4.1揮発性

  • Volatileは、変数の値が
    さまざまなスレッドによって変更されることを示すために使用されます
  • 変数へのアクセスはのみに1つのスレッドに与えられ
    た時間
    public volatile int counter = 0;

4.2揮発性の一般的なトラップ

配列
arr []を揮発性として宣言すると、それは

  1. 配列への参照は揮発性です。
  2. 個々のフィールドアクセス(例:arr [5])はスレッドセーフではありません

単項演算
(++、-)はアトミックではありません

volatile int i; 
... 
i += 5; //NOT SAFE

4.3使用法:キャッシュを停止する

変数が変更された
場合、変数をvolatileに設定すると、別のスレッドのキャッシュが古くなる可能性があります。

  1. この変数の値がスレッドローカルにキャッシュされることはありません
  2. すべての読み取りと書き込みは「メインメモリ」に直接送られます。
public class StoppableTask extends Thread {
    
    
private boolean pleaseStop; 
// private volatile boolean pleaseStop
//Because of volatile while loop cannot cache  
// Re-checks pleaseStop every iteration
public void run() {
    
    
    // While loop caches pleaseStop variable 
    //This loop will never end
    while (!pleaseStop)  {
    
     // do some stuff... } }
public void tellMeToStop()
    {
    
     pleaseStop = true; } }

4.4揮発性物質を使用しない場合

  1. 最終を宣言したフィールド(変更しない)
  2. 1つのスレッドのみがアクセスする変数
  3. 複雑な操作(x = x + 5のようなものでも)

4.5別の点:Thread.yield()はThread.sleep()よりも優れている可能性があります

  1. yieldは、スレッドの継続的な実行を停止し、オペレーティングシステムにしばらく時間を与えます。
  2. イールドはスレッドのターンをあきらめ
    、次のラウンドでそれを取り戻します。
  3. sleep()は、プロセスをウェイクアップするある種のタイマーを含むシステムを作成するため、オーバーヘッドがわずかに大きくなります。(基本的に実装に依存します)
    したがって、歩留まりが向上する場合があります

宿題

  1. いくつかの異なるスレッドを作成します
    1. こんにちはの印刷を絶えずループするもの
    2. 1秒間のスリープを挟んでhelloの印刷をループするもの
  2. スレッドを中断して、何が起こるか見てください!
  3. それらに割り込みサポートを追加
    して、割り込みでループ停止できるようにします
  4. 共有変数を作成してください完了してスレッドを終了してください
    1. 揮発性の有無にかかわらず試してみてください…

おすすめ

転載: blog.csdn.net/GreatSimulation/article/details/108818590