検索
ホームページJava&#&チュートリアルJava マルチスレッド プログラミングにおけるスレッドの開始、中断、終了の詳細な説明

スレッドの起動:
1. start() と run() の違いの説明
start(): その機能は新しいスレッドを開始することであり、新しいスレッドは対応する run() メソッドを実行します。 start() を繰り返し呼び出すことはできません。
run(): run() は通常のメンバー メソッドと同様で、繰り返し呼び出すことができます。 run() を単独で呼び出した場合、run() は現在のスレッドで実行され、新しいスレッドは開始されません。
以下はコードで説明します。

class MyThread extends Thread{
  public void run(){
    ...
  }
};
MyThread mythread = new MyThread();

mythread.start() は新しいスレッドを開始し、新しいスレッドで run() メソッドを実行します。
Mythread.run() は現在のスレッドで run() メソッドを直接実行し、run() を実行するための新しいスレッドを開始しません。

2. start() と run() の違いの例
以下では、簡単な例を使用してそれらの違いを示します。ソースコードは次のとおりです。

// Demo.java 的源码
class MyThread extends Thread{
  public MyThread(String name) {
    super(name);
  }
 
  public void run(){
    System.out.println(Thread.currentThread().getName()+" is running");
  }
};
 
public class Demo {
  public static void main(String[] args) {
    Thread mythread=new MyThread("mythread");
 
    System.out.println(Thread.currentThread().getName()+" call mythread.run()");
    mythread.run();
 
    System.out.println(Thread.currentThread().getName()+" call mythread.start()");
    mythread.start();
  }
}

実行結果:

main call mythread.run()
main is running
main call mythread.start()
mythread is running

結果の説明:
(1) Thread.currentThread().getName() は、「」の名前を取得するために使用されます。現在のスレッド」。現在のスレッドは、CPU で実行がスケジュールされているスレッドを指します。
(2) mythread.run() は「メインスレッド main」で呼び出され、run() メソッドは「メインスレッド main」上で直接実行されます。
(3) mythread.start() は「スレッド mythread」を開始します。「スレッド mythread」が開始された後、run() メソッドが呼び出されます。この時点では、run() メソッドは「スレッド」上で実行されます。神話」。

スレッドの中断と終了

1. スレッドの中断: このスレッドを中断するには、interrupt()
interrupt() を使用します。
このスレッドはそれ自体に割り込むことができます。他のスレッドがこのスレッドのinterrupt()メソッドを呼び出すと、checkAccess()を通じて権限がチェックされます。これにより、SecurityException がスローされる場合があります。
このスレッドがブロック状態にある場合: スレッドの wait()、wait(long)、または wait(long, int) を呼び出すと、スレッドは待機 (ブロック) 状態になります。または、スレッドの join()、join(long) を呼び出すと、スレッドは待機 (ブロック) 状態になります。 )、join(long, int)、sleep(long)、sleep(long, int) もブロック状態にします。スレッドがブロックされているときにそのスレッドがその中断() メソッドを呼び出すと、その「中断ステータス」がクリアされ、InterruptedException が受信されます。たとえば、スレッドは wait() によってブロック状態に入り、interrupt() によってスレッドを中断します。interrupt() を呼び出すとすぐにスレッドの割り込みフラグが「true」に設定されますが、スレッドはブロック状態にあるため、 「割り込みフラグ」は即座に「false」にクリアされ、同時にInterruptedExceptionが発生します。
セレクターでスレッドがブロックされている場合、interrupt(); によって中断されると、スレッドの割り込みフラグが true に設定され、選択操作からすぐに戻ります。
上記の状況に該当しない場合、スレッドがinterrupt()を通じて中断されると、その中断フラグは「true」に設定されます。
「終了したスレッド」を中断しても何も起こりません。

2. スレッドの終了
Thread の stop() メソッドと submit() メソッドは、本質的に安全性が低いため、使用しないことをお勧めします。
以下では、まず「ブロック状態」と「実行状態」それぞれのスレッドの終了方法について説明し、その後一般的な方法をまとめます。
1.「ブロック状態」のスレッドを終了する
通常、「ブロック状態」のスレッドを「中断」により終了させます。
sleep()、wait()、join() などのメソッドの呼び出しによりスレッドがブロック状態になると、この時点でスレッドの中断() が呼び出される場合、スレッドの割り込みフラグは true に設定されます。ブロック状態であるため、割り込みマークがクリアされ、InterruptedException が発生します。スレッドは、適切なまで InterruptedException を配置することで終了できます。形式は次のとおりです。

@Override
public void run() {
  try {
    while (true) {
      // 执行任务...
    }
  } catch (InterruptedException ie) {
    // 由于产生InterruptedException异常,退出while(true)循环,线程终止!
  }
}

説明: スレッドがブロックされているときに、スレッドの中断() を呼び出すと、InterruptedException 割り込みが生成されます。 。割り込みは while(true) の外側でキャプチャされるため、while(true) ループを終了します。
注: InterruptedException のキャプチャは通常、while(true) ループ本体の外側に配置されるため、例外が発生したときに while(true) ループが終了します。それ以外の場合、InterruptedException が while(true) ループ本体内にある場合は、追加の終了処理を追加する必要があります。形式は次のとおりです。

@Override
public void run() {
  while (true) {
    try {
      // 执行任务...
    } catch (InterruptedException ie) {
      // InterruptedException在while(true)循环体内。
      // 当线程产生了InterruptedException异常时,while(true)仍能继续运行!需要手动退出
      break;
    }
  }
}

説明: 上記の InterruptedException 例外は whle(true) 内でキャプチャされます。 InterruptedException 例外が発生した場合、その例外は catch によって処理される以外の while(true) ループ本体内にあります。while(true) ループ本体を終了するには、while(true) を終了するための追加の操作が必要です。
2.「実行状態」のスレッドを終了する
通常、「実行状態」のスレッドを「マーク」で終了します。その中には「中断マーク」と「追加加算マーク」が含まれます。
(1) 「割り込みフラグ」によりスレッドを終了します。
フォームは次のとおりです:

@Override
public void run() {
  while (!isInterrupted()) {
    // 执行任务...
  }
}

说明:isInterrupted()是判断线程的中断标记是不是为true。当线程处于运行状态,并且我们需要终止它时;可以调用线程的interrupt()方法,使用线程的中断标记为true,即isInterrupted()会返回true。此时,就会退出while循环。
注意:interrupt()并不会终止处于“运行状态”的线程!它会将线程的中断标记设为true。
(2) 通过“额外添加标记”。
形式如下:

private volatile boolean flag= true;
protected void stopTask() {
  flag = false;
}
 
@Override
public void run() {
  while (flag) {
    // 执行任务...
  }
}

   

说明:线程中有一个flag标记,它的默认值是true;并且我们提供stopTask()来设置flag标记。当我们需要终止该线程时,调用该线程的stopTask()方法就可以让线程退出while循环。
注意:将flag定义为volatile类型,是为了保证flag的可见性。即其它线程通过stopTask()修改了flag之后,本线程能看到修改后的flag的值。
综合线程处于“阻塞状态”和“运行状态”的终止方式,比较通用的终止线程的形式如下:

@Override
public void run() {
  try {
    // 1. isInterrupted()保证,只要中断标记为true就终止线程。
    while (!isInterrupted()) {
      // 执行任务...
    }
  } catch (InterruptedException ie) {
    // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
  }
}

   

3. 终止线程的示例
interrupt()常常被用来终止“阻塞状态”线程。参考下面示例:

// Demo1.java的源码
class MyThread extends Thread {
 
  public MyThread(String name) {
    super(name);
  }
 
  @Override
  public void run() {
    try {
      int i=0;
      while (!isInterrupted()) {
        Thread.sleep(100); // 休眠100ms
        i++;
        System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
      }
    } catch (InterruptedException e) {
      System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
    }
  }
}
 
public class Demo1 {
 
  public static void main(String[] args) {
    try {
      Thread t1 = new MyThread("t1"); // 新建“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
 
      t1.start();           // 启动“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
 
      // 主线程休眠300ms,然后主线程给t1发“中断”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
 
      // 主线程休眠300ms,然后查看t1的状态。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

   

运行结果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

   

结果说明:
(1) 主线程main中通过new MyThread("t1")创建线程t1,之后通过t1.start()启动线程t1。
(2) t1启动之后,会不断的检查它的中断标记,如果中断标记为“false”;则休眠100ms。
(3) t1休眠之后,会切换到主线程main;主线程再次运行时,会执行t1.interrupt()中断线程t1。t1收到中断指令之后,会将t1的中断标记设置“false”,而且会抛出InterruptedException异常。在t1的run()方法中,是在循环体while之外捕获的异常;因此循环被终止。
我们对上面的结果进行小小的修改,将run()方法中捕获InterruptedException异常的代码块移到while循环体内。

// Demo2.java的源码
class MyThread extends Thread {
 
  public MyThread(String name) {
    super(name);
  }
 
  @Override
  public void run() {
    int i=0;
    while (!isInterrupted()) {
      try {
        Thread.sleep(100); // 休眠100ms
      } catch (InterruptedException ie) {
        System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
      }
      i++;
      System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
    }
  }
}
 
public class Demo2 {
 
  public static void main(String[] args) {
    try {
      Thread t1 = new MyThread("t1"); // 新建“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
 
      t1.start();           // 启动“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
 
      // 主线程休眠300ms,然后主线程给t1发“中断”指令。
      Thread.sleep(300);
      t1.interrupt();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
 
      // 主线程休眠300ms,然后查看t1的状态。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

   

运行结果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...

   

结果说明:
程序进入了死循环!
为什么会这样呢?这是因为,t1在“等待(阻塞)状态”时,被interrupt()中断;此时,会清除中断标记[即isInterrupted()会返回false],而且会抛出InterruptedException异常[该异常在while循环体内被捕获]。因此,t1理所当然的会进入死循环了。
解决该问题,需要我们在捕获异常时,额外的进行退出while循环的处理。例如,在MyThread的catch(InterruptedException)中添加break 或 return就能解决该问题。
下面是通过“额外添加标记”的方式终止“状态状态”的线程的示例:

// Demo3.java的源码
class MyThread extends Thread {
 
  private volatile boolean flag= true;
  public void stopTask() {
    flag = false;
  }
 
  public MyThread(String name) {
    super(name);
  }
 
  @Override
  public void run() {
    synchronized(this) {
      try {
        int i=0;
        while (flag) {
          Thread.sleep(100); // 休眠100ms
          i++;
          System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
        }
      } catch (InterruptedException ie) {
        System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
      }
    }
  }
}
 
public class Demo3 {
 
  public static void main(String[] args) {
    try {
      MyThread t1 = new MyThread("t1"); // 新建“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
 
      t1.start();           // 启动“线程t1”
      System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
 
      // 主线程休眠300ms,然后主线程给t1发“中断”指令。
      Thread.sleep(300);
      t1.stopTask();
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
 
      // 主线程休眠300ms,然后查看t1的状态。
      Thread.sleep(300);
      System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

   

运行结果:

t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.

   


更多详解Java多线程编程中线程的启动、中断或终止操作相关文章请关注PHP中文网!


声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?Mar 17, 2025 pm 05:46 PM

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 05:45 PM

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?Mar 17, 2025 pm 05:44 PM

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?Mar 17, 2025 pm 05:43 PM

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Mar 17, 2025 pm 05:35 PM

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。