JAvaマルチスレッドの3つの構築方法

7913 ワード

java  マルチスレッドの3つの構築方法
Threadクラスの継承スレッドクラスの作成

public class Thread extends Object implements Runnable
  • Threadクラスのサブクラスを定義しrun()メソッド
  • を書き換える.
  • は、スレッドオブジェクト
  • を作成するThreadサブクラスのインスタンスを作成する.
  • スレッドオブジェクトを呼び出す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を継承するクラスで使用する場合はthis参照のみ
    上の2つのサブスレッドとプライマリスレッドはランダムに切り替えられます.また、Threadを継承するクラスを使用しているため、2つのサブスレッドはリソースを共有できません.
    start()メソッド呼び出し後は直ちにマルチスレッドコードを実行するのではなく,そのスレッドを実行可能な状態にプログラミングし,いつ実行するかはオペレーティングシステムによって決定される.
    Runnableインタフェースを実装してスレッドクラスを作成する
    
    public Thread() 
    public Thread(Runnable target) 
    public Thread(Runnable target,String name)
  • Runnableインタフェースの実装クラスを定義し、そのインタフェースのrun()メソッド
  • を書き換える.
  • Runnableインプリメンテーションクラスのインスタンスを作成し、これをThreadのtargetとして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があったからこそ;共有リソースは1つしかありませんが、これは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
    

    同じようにprivate int count=15という共通のインスタンス化オブジェクトがあるからこそ,Runnableを実現するクラスがリソースを共有できる.
    では、なぜThreadクラスのサブクラスを継承してRunableインタフェースを実現するクラスがリソースを共有する際に異なるのでしょうか.
    Javaでは単一継承しかサポートできないため、単一継承の特徴は1つのサブクラスしか継承できないことを意味し、Runnablインタフェース後に多くのクラスと複数のスレッドで1つのリソースを共有できる操作を行うことができる.
    CallableとFutureを使用したスレッドの作成
    CallableはどうしてもRunnableインタフェースの強化版のように見えますが、CallableにはRunnableのrun()メソッドに相当するcall()メソッドがありますが、機能はさらに強力です.
    call()メソッドには戻り値call()メソッドがあり、放出異常を宣言できます.
    Callableインタフェースには汎用制限があり,Callableインタフェースの汎用パラメータタイプはcall()メソッドの戻り値タイプと同じである.また、Callableインタフェースは関数インタフェースであるため、Lambda式を使用してCallableオブジェクトRunnableインタフェースを作成することも関数インタフェースであるため、Lambda式を使用してRunnableオブジェクトを作成することもできます
  • Callableインタフェースの実装クラスを作成し、スレッド実行体として、Callable実装クラスのインスタンス
  • を作成するcall()メソッドを実装する.
  • FutureTaskクラスを使用してCallableオブジェクトをパッケージングする.このFutureTaskオブジェクトはCallableオブジェクトのcall()メソッド
  • をパッケージングする.
  • FutureTaskクラスオブジェクトをThreadオブジェクトのtargetとして使用する新しいスレッド
  • を作成して起動する.
  • FutureTaskオブジェクトのget()メソッドを呼び出し、サブスレッド終了後の戻り値
  • を得る.
    
    public class ThirdThread implements Callable {
      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 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();
        }
      }
    }
    
    

    Lambda式のCallableとFutureを使用して作成されたスレッド
    
    public class ThirdThread{
      public static void main(String[] args){
        ThirdThread tt=new ThirdThread();
        //   Lambda     Callable  
        //  FutureTask  Callable  
        FutureTask task=new FutureTask((Callable)()->{
          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();
        }
      }
    }
    
    

    もし疑問があれば伝言を残してあるいは当駅のコミュニティに行って討論を交流して、読書に感謝して、みんなを助けることができることを望んで、みんなの当駅に対する支持に感謝します!