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

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

黄舟
リリース: 2017-09-08 11:15:15
オリジナル
1236 人が閲覧しました

この記事では、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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート