Java でマルチスレッドを構築する 3 つの方法を共有します

黄舟
リリース: 2017-09-18 09:37:35
オリジナル
1371 人が閲覧しました

この記事では、Java マルチスレッドの 3 つの構築方法に関する関連情報を主に紹介します。ここでは、非常に重要な基本知識を習得できることを願っています。構築メソッド

Thread クラスを継承してスレッド クラスを作成します

public class Thread extends Object implements Runnable
ログイン後にコピー


Thread クラスのサブクラスを定義し、その run() メソッドをオーバーライドします
  1. Thread サブクラスのインスタンスを作成しますつまり、スレッドオブジェクトを作成しました
  2. スレッドオブジェクトのstart()メソッドを呼び出してスレッドを開始します

public class FirstThread extends Thread {
  public void run(){
    for(int i=0;i<100;i++){
      /*
       * Thread类已经继承了Object
       * Object类创建了name选项 并且有其getName(),setName()方法
       * 在继承Thread的类里面使用时只需要用this引用
      */
      System.out.println(this.getName()+" "+i);
    }
  }

  public static void main(String[] args) {
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);
      if(i==20){
        new FirstThread().start();
        new FirstThread().start();
      }
    }
  }

}
ログイン後にコピー

ThreadクラスがObjectを継承しました

Objectクラスがnameオプションを作成しましたgetName()、setName()メソッドがあります

Threadを継承するクラスで使用する場合は、この参照を使用するだけで済みます

上記の2つのセカンダリスレッドとメインスレッドはランダムに切り替わり、継承するクラスがスレッドが使用されているため、2 つのセカンダリ スレッドはリソースを共有できません

start() メソッドが呼び出された後、マルチスレッド コードはすぐには実行されませんが、スレッド プログラミングが実行可能になるタイミングはオペレーティング システムによって決定されます。


Runnableインターフェースを実装してスレッドクラスを作成します

public Thread() 
public Thread(Runnable target) 
public Thread(Runnable target,String name)
ログイン後にコピー


Runnableインターフェースの実装クラスを定義し、インターフェースのrun()メソッドをオーバーライドします
  • 実行可能な実装クラスを使用して Thread オブジェクトを作成します。 Thread オブジェクトは実際のスレッド オブジェクトです。

public class SecondThread implements Runnable {
  public void run(){
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);
    }
  }

  public static void main(String[] args) {
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" "+i);

      if(i==20){
        SecondThread st=new SecondThread();
        //通过new Thread(target,name)创建线程
        new Thread(st,"新线程1").start();
        new Thread(st,"新线程2").start();
      }
    }
  }
}
ログイン後にコピー

上記の結果は、2 つのセカンダリ スレッドとメイン スレッドがランダムに切り替わりますが、共有するリソースがまったくないため、共有リソースはありません。

start() メソッドが呼び出された後、マルチスレッド コードはすぐには実行されませんが、スレッド プログラミングをいつ実行するかはオペレーティング システムによって決定されます

Thread クラスを継承する共有リソースの詳細な説明そして、Runnableインターフェースを作成します


共有できるリソースのみがある場合は、同じインスタンス化オブジェクトが使用されます。 2 つの作成方法は、リソースを共有する場合のみ異なります。それ以外の場合、共有リソースは通常、private static 修飾子を使用して変更されます。

class Thread1 extends Thread{ 
  private int count=5; 
  private String name; 
  public Thread1(String name) { 
    this.name=name; 
  } 
  public void run() { 
    for (int i = 0; i < 5; i++) { 
      System.out.println(name + "运行 count= " + count--); 
      try { 
        sleep((int) Math.random() * 10); 
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } 
    } 

  } 
} 

public class Main { 

  public static void main(String[] args) { 
    Thread1 mTh1=new Thread1("A"); 
    Thread1 mTh2=new Thread1("B"); 
    mTh1.start(); 
    mTh2.start(); 

  } 

}
ログイン後にコピー


B运行 count= 5 
A运行 count= 5 
B运行 count= 4 
B运行 count= 3 
B运行 count= 2 
B运行 count= 1 
A运行 count= 4 
A运行 count= 3 
A运行 count= 2 
A运行 count= 1
ログイン後にコピー

private int count=5;の文があるからこそリソースを共有できますが、これはThreadクラスを継承したサブクラスなのでリソースを共有することはできません

class Thread2 implements Runnable{ 
  private int count=15; 
  public void run() { 
     for (int i = 0; i < 5; i++) { 
       System.out.println(Thread.currentThread().getName() + "运行 count= " + count--); 
        try { 
          Thread.sleep((int) Math.random() * 10); 
        } catch (InterruptedException e) { 
          e.printStackTrace(); 
        } 
      } 

  } 

} 
public class Main { 

  public static void main(String[] args) { 

    Thread2 my = new Thread2(); 
      new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常   
      new Thread(my, "D").start(); 
      new Thread(my, "E").start(); 
  } 

}
ログイン後にコピー


C运行 count= 15 
D运行 count= 14 
E运行 count= 13 
D运行 count= 12 
D运行 count= 10 
D运行 count= 9 
D运行 count= 8 
C运行 count= 11 
E运行 count= 12 
C运行 count= 7 
E运行 count= 6 
C运行 count= 5 
E运行 count= 4 
C运行 count= 3 
E运行 count= 2
ログイン後にコピー

同様に、Runnable を実装するクラスがリソースを共有できるのは、private int count=15 の共通のインスタンス化オブジェクトのおかげです

では、なぜ Thread クラスを継承するサブクラスと、Thread クラスを実装するクラスの間でリソースの共有に違いがあるのでしょうか。実行可能なインターフェイス?

Javaは単一継承のみをサポートできるため、単一継承機能は1つのサブクラスのみが継承でき、Runnablインターフェースの後に多くのクラスが続くことができることを意味し、その結果、複数のスレッドがリソースを共有できます


CallableとFuture createを使用するスレッド

Callable は、Runnable インターフェースの拡張バージョンのように見えます。Callable には、Runnable の run() メソッドと同等の call() メソッドがありますが、関数はより強力です:

call() メソッドは戻り値を持つことができます。

call() メソッドは例外をスローするように宣言できます


Callable インターフェイスには一般的な制限があります。 Callable インターフェイスのジェネリック パラメーターの型は call() メソッドの戻り値の型と同じです。 さらに、Callable インターフェイスは関数型インターフェイスであるため、Lambda 式を使用して Callable オブジェクトを作成できます。Runnable インターフェイスも関数型インターフェイスなので、Lambda 式を使用して Runnable オブジェクトを作成することもできます。 Callable インターフェースの実装クラスと call() メソッドを実装すると、call() メソッドがスレッドの実行本体として使用され、Callable 実装クラスのインスタンスを作成します

FutureTask クラスを使用して Callable オブジェクトをラップします, FutureTask オブジェクトは、Callable オブジェクトの call() メソッドをカプセル化します

  1. FutureTask クラス オブジェクトを Thread オブジェクトのターゲットとして使用して、新しいスレッドを作成して開始します

  2. FutureTask の get() メソッドを呼び出します子スレッド終了後に戻り値を取得するオブジェクト

  3. public class ThirdThread implements Callable<Integer> {
      public Integer call(){
        int i=0;
        for(;i<100;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
        }
        return i;
      }
    
      public static void main(String[] args){
        ThirdThread tt=new ThirdThread();
        FutureTask<Integer> task=new FutureTask<>(tt);
        Thread t=new Thread(task,"有返回值的线程");
        for(int i=0;i<100;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
          if(i==20){
            t.start();
          }
        }
        try{
          System.out.println("返回值是:"+task.get());
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    }
    ログイン後にコピー
  4. ラムダ式を使用する Callable と Future によって作成されたスレッド

public class ThirdThread{
  public static void main(String[] args){
    ThirdThread tt=new ThirdThread();
    //先使用Lambda表达式创建Callable<Integer>对象
    //使用FutureTask封装Callable对象
    FutureTask<Integer> task=new FutureTask<Integer>((Callable<Integer>)()->{
      int i=0;
      for(;i<100;i++){
        System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
      }
      return i;
    });

    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
      if(i==20){
        new Thread(task,"有返回值的线程").start();
      }
    }
    try{
      System.out.println("子线程的返回值"+task.get());
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}
ログイン後にコピー

以上がJava でマルチスレッドを構築する 3 つの方法を共有しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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