ホームページ Java &#&チュートリアル Java でのマルチスレッドの使用方法の詳細な説明

Java でのマルチスレッドの使用方法の詳細な説明

Sep 08, 2017 am 11:15 AM
java 使用 詳しい説明

この記事では、Java マルチスレッドの詳しい使い方についての関連情報を中心に紹介しますので、困っている方の参考になれば幸いです

Java マルチスレッドの使い方を詳しく紹介します。最も包括的な Java マルチスレッドのスレッド使用状況分析。Java のマルチスレッド メカニズムについて詳しく調べていない場合、この記事は Java マルチスレッドの原理と使用法をより完全に理解するのに役立ちます。

1. スレッドを作成します

Java でスレッドを作成するには、Thread クラスを使用する方法と Runnable インターフェイスを使用する方法の 2 つがあります。 Runnable インターフェイスを使用する場合は、Thread インスタンスを作成する必要があります。したがって、Thread クラスまたは Runnable インターフェイスを通じてスレッドを作成する場合は、Thread クラスまたはそのサブクラスのインスタンスを作成する必要があります。スレッド コンストラクター:

public Thread( );
public Thread(Runnable target);
public Thread(String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name, long stackSize);
ログイン後にコピー

方法 1: Thread クラスを継承し、run メソッドをオーバーライドする

public class ThreadDemo1 {
   public static void main(String[] args){
     Demo d = new Demo();
     d.start();
     for(int i=0;i<60;i++){
       System.out.println(Thread.currentThread().getName()+i);
     }

   }
 }
 class Demo extends Thread{
   public void run(){
     for(int i=0;i<60;i++){
       System.out.println(Thread.currentThread().getName()+i);
     }
   }
 }
ログイン後にコピー

方法 2:

public class ThreadDemo2 {
  public static void main(String[] args){
    Demo2 d =new Demo2();
    Thread t = new Thread(d);
    t.start();
    for(int x=0;x<60;x++){
      System.out.println(Thread.currentThread().getName()+x);
    }
  }
}
class Demo2 implements Runnable{
  public void run(){
    for(int x=0;x<60;x++){
      System.out.println(Thread.currentThread().getName()+x);
    }
  }
}
ログイン後にコピー


2. スレッド

のライフ サイクルは次のとおりです。の人の誕生、老、病、死と同じように、スレッドも開始 (待機)、実行、中断、停止という 4 つの異なる状態を経る必要があります。これら 4 つの状態は、Thread クラスのメソッドを通じて制御できます。 Thread クラスのこれら 4 つの状態に関連するメソッドを以下に示します。

// 开始线程
publicvoid start( );
publicvoid run( );
// 挂起和唤醒线程
publicvoid resume( );   // 不建议使用
publicvoid suspend( );  // 不建议使用
publicstaticvoid sleep(long millis);
publicstaticvoid sleep(long millis, int nanos);
// 终止线程
publicvoid stop( );    // 不建议使用
publicvoid interrupt( );
// 得到线程状态
publicboolean isAlive( );
publicboolean isInterrupted( );
publicstaticboolean interrupted( );
// join方法
publicvoid join( ) throws InterruptedException;
ログイン後にコピー

スレッドは確立直後に run メソッド内のコードを実行せず、待機状態になります。スレッドが待機状態にある場合、Thread クラスのメソッドを通じて、スレッドの優先順位 (setPriority)、スレッド名 (setName)、スレッド タイプ (setDaemon) などのスレッドのさまざまな属性を設定できます。

start メソッドが呼び出されると、スレッドは run メソッド内のコードの実行を開始します。スレッドは実行状態になります。 Thread クラスの isAlive メソッドを使用して、スレッドが実行されているかどうかを確認できます。スレッドが実行状態にある場合、isAlive は true を返します。isAlive が false を返す場合、スレッドは待機状態または停止状態にある可能性があります。次のコードは、スレッドの作成、実行、停止の 3 つの状態間の切り替えを示し、対応する isAlive 戻り値を出力します。

スレッドが run メソッドの実行を開始すると、run メソッドが完了するまでスレッドは終了しません。ただし、スレッドの実行中に、2 つの方法でスレッドの実行を一時的に停止できます。これら 2 つの方法はサスペンドとスリープです。サスペンドを使用してスレッドを一時停止した後、再開メソッドを使用してスレッドをウェイクアップできます。 sleep を使用してスレッドをスリープ状態にした後、スレッドは設定された時間が経過した後にのみ準備完了状態になることができます (スレッドのスリープ終了後、スレッドはすぐには実行されない場合がありますが、システムがスケジュールするのを待って準備完了状態になるだけです)。 。

sleep メソッドを使用する際の注意点は 2 つあります:

1. sleep メソッドには 2 つのオーバーロードされたフォームがあり、オーバーロードされたフォームの 1 つはミリ秒だけでなくナノ秒も設定できます (1,000,000 ナノ秒は 1 ミリ秒に相当します)。ただし、ほとんどのオペレーティング システム プラットフォームの Java 仮想マシンはナノ秒まで正確ではないため、スリープにナノ秒が設定されている場合、Java 仮想マシンはこの値に最も近いミリ秒を取得します。

2. sleep メソッドを使用する場合は、Throws または try{…}catch{…} を使用する必要があります。 run メソッドでは throw を使用できないため、try{…}catch{…} のみを使用できます。スレッドがスリープ状態で、割り込みメソッドを使用してスレッドを中断すると、スリープは InterruptedException をスローします。 sleep メソッドは次のように定義されます:

publicstaticvoid sleep(long millis) throws InterruptedException
publicstaticvoid sleep(long millis, int nanos) throws InterruptedException
ログイン後にコピー

スレッドを終了するには 3 つの方法があります。

1. 終了フラグを使用してスレッドを正常に終了します。つまり、run メソッドが完了するとスレッドが終了します。

2. stop メソッドを使用してスレッドを強制的に終了します (サスペンドや再開と同様に、停止によっても予期しない結果が生じる可能性があるため、この方法はお勧めできません)。

3. スレッドを中断するには、interrupt メソッドを使用します。

1. exit フラグを使用してスレッドを終了します

run メソッドが実行されると、スレッドは終了します。ただし、run メソッドが終了しない場合があります。たとえば、スレッドはサーバー プログラムでクライアントの要求や、周期的な処理を必要とするその他のタスクを監視するために使用されます。この場合、これらのタスクは通常、while ループなどのループ内に配置されます。ループを永久に実行したい場合は、while(true){…} を使用して処理できます。ただし、特定の条件下で while ループを終了させたい場合、最も直接的な方法は、ブール型フラグを設定し、このフラグを true または false に設定して while ループを終了するかどうかを制御することです。終了フラグを使用してスレッドを終了する例を以下に示します。

join メソッドの機能は、非同期実行スレッドを同期実行にすることです。つまり、スレッド インスタンスの start メソッドが呼び出されると、このメソッドはすぐに戻ります。start メソッドの呼び出し後にこのスレッドによって計算された値を使用する必要がある場合は、join メソッドを使用する必要があります。 join メソッドを使用しない場合、start メソッドに続くステートメントの実行時にスレッドが実行されるという保証はありません。 join メソッドを使用した後は、このスレッドが終了するまでプログラムは実行を続行しません。次のコードは、結合の使用法を示しています。

3. マルチスレッドのセキュリティの問題

问题原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致共享数据的错误。

解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不执行。

同步代码块:


public class ThreadDemo3 {
  public static void main(String[] args){
    Ticket t =new Ticket();
    Thread t1 = new Thread(t,"窗口一");
    Thread t2 = new Thread(t,"窗口二");
    Thread t3 = new Thread(t,"窗口三");
    Thread t4 = new Thread(t,"窗口四");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
  }
}
class Ticket implements Runnable{
  private int ticket =400;
  public void run(){
    while(true){
      synchronized (new Object()) {
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        if(ticket<=0)
          break;
        System.out.println(Thread.currentThread().getName()+"---卖出"+ticket--);
      }
    }
  }
}
ログイン後にコピー

同步函数


public class ThreadDemo3 {
  public static void main(String[] args){
    Ticket t =new Ticket();
    Thread t1 = new Thread(t,"窗口一");
    Thread t2 = new Thread(t,"窗口二");
    Thread t3 = new Thread(t,"窗口三");
    Thread t4 = new Thread(t,"窗口四");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
  }
}
class Ticket implements Runnable{
  private int ticket = 4000;
  public synchronized void saleTicket(){
    if(ticket>0)
      System.out.println(Thread.currentThread().getName()+"卖出了"+ticket--);

  }
  public void run(){
    while(true){
      saleTicket();
    }
  }
}
ログイン後にコピー

同步函数锁是this 静态同步函数锁是class

线程间的通信


public class ThreadDemo3 {
  public static void main(String[] args){
    class Person{
      public String name;
      private String gender;
      public void set(String name,String gender){
        this.name =name;
        this.gender =gender;
      }
      public void get(){
        System.out.println(this.name+"...."+this.gender);
      }
    }
    final Person p =new Person();
    new Thread(new Runnable(){
      public void run(){
        int x=0;
        while(true){
          if(x==0){
            p.set("张三", "男");
          }else{
            p.set("lili", "nv");
          }
          x=(x+1)%2;
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          p.get();
        }
      }
    }).start();
  }
}
/*
张三....男
张三....男
lili....nv
lili....男
张三....nv
lili....男
*/
ログイン後にコピー

修改上面代码


public class ThreadDemo3 {
   public static void main(String[] args){
     class Person{
       public String name;
       private String gender;
       public void set(String name,String gender){
         this.name =name;
         this.gender =gender;
       }
       public void get(){
         System.out.println(this.name+"...."+this.gender);
       }
     }
     final Person p =new Person();
     new Thread(new Runnable(){
       public void run(){
         int x=0;
         while(true){
           synchronized (p) {
             if(x==0){
               p.set("张三", "男");
             }else{
               p.set("lili", "nv");
             }
             x=(x+1)%2;  
           }

         }
       }
     }).start();
     new Thread(new Runnable(){
       public void run(){
         while(true){
           synchronized (p) {
             p.get();
           }
         }
       }
     }).start();
   }

 }
 /*
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 张三....男
 张三....男
 张三....男
 张三....男
 */
ログイン後にコピー

等待唤醒机制


/*
 *线程等待唤醒机制
 *等待和唤醒必须是同一把锁 
 */
public class ThreadDemo3 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Person{
      public String name;
      private String gender;
      public void set(String name,String gender){
        this.name =name;
        this.gender =gender;
      }
      public void get(){
        System.out.println(this.name+"...."+this.gender);
      }
    }
    final Person p =new Person();
    new Thread(new Runnable(){
      public void run(){
        int x=0;
        while(true){
          synchronized (p) {
            if(flags)
              try {
                p.wait();
              } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              };
            if(x==0){
              p.set("张三", "男");
            }else{
              p.set("lili", "nv");
            }
            x=(x+1)%2;
            flags =true;
            p.notifyAll();
          }
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          synchronized (p) {
            if(!flags)
              try {
                p.wait();
              } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              };
            p.get();
            flags =false;
            p.notifyAll();
            }
        }
      }
    }).start();
  }
}
ログイン後にコピー

生产消费机制一


public class ThreadDemo4 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Goods{
      private String name;
      private int num;
      public synchronized void produce(String name){
        if(flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        this.name =name+"编号:"+num++;
        System.out.println("生产了...."+this.name);
        flags =true;
        notifyAll();
      }
      public synchronized void consume(){
        if(!flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        System.out.println("消费了******"+name);
        flags =false;
        notifyAll();
      }

    }
    final Goods g =new Goods();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    }).start();
  }
}
ログイン後にコピー

生产消费机制2


public class ThreadDemo4 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Goods{
      private String name;
      private int num;
      public synchronized void produce(String name){
        while(flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        this.name =name+"编号:"+num++;
        System.out.println(Thread.currentThread().getName()+"生产了...."+this.name);
        flags =true;
        notifyAll();
      }
      public synchronized void consume(){
        while(!flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        System.out.println(Thread.currentThread().getName()+"消费了******"+name);
        flags =false;
        notifyAll();
      }

    }
    final Goods g =new Goods();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    },"生产者一号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    },"生产者二号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    },"消费者一号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    },"消费者二号").start();
  }
}
/*
消费者二号消费了******商品编号:48049
生产者一号生产了....商品编号:48050
消费者一号消费了******商品编号:48050
生产者一号生产了....商品编号:48051
消费者二号消费了******商品编号:48051
生产者二号生产了....商品编号:48052
消费者二号消费了******商品编号:48052
生产者一号生产了....商品编号:48053
消费者一号消费了******商品编号:48053
生产者一号生产了....商品编号:48054
消费者二号消费了******商品编号:48054
生产者二号生产了....商品编号:48055
消费者二号消费了******商品编号:48055
*/
ログイン後にコピー

以上がJava でのマルチスレッドの使用方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホット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ヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

See all articles