[Java] Javaベースのマルチスレッド

マルチスレッド

概念:スレッドとは、プロセス内の単一の順次制御フローを指します。プロセス内で複数のスレッドを同時に実行でき、各スレッドは異なるタスクを並行して実行します。

ライフサイクル:

img

  • 新しいステータス:

    使用後は、新たなキーワードとスレッドのスレッドオブジェクトを作成するには、クラスまたはそのサブクラスを、スレッドオブジェクトは、新しく作成された状態になっています。プログラムこのスレッドを開始するまで、この状態を維持します。

  • 準備完了状態

    スレッドオブジェクトがstart()メソッドを呼び出すと、スレッドは準備完了状態になります。作動可能状態のスレッドは作動可能キューにあり、JVM内のスレッド・スケジューラーのスケジューリングを待ちます。

  • 稼働状況

    準備完了状態のスレッドがCPUリソースを獲得すると、そのスレッドはrun()を実行でき、スレッドは実行状態になります。実行状態のスレッドは最も複雑で、ブロックされ、準備ができて、停止する可能性があります。

  • ブロック状態

    スレッドがスリープ(sleep)、suspend(suspend)、およびその他のメソッドを実行する場合、占有されたリソースを失った後、スレッドは実行状態からブロッキング状態に入ります。スリープタイムが経過した後、またはデバイスリソースが取得された後に、準備完了状態に再び入ることができます。それは3つのタイプに分けることができます:

    • ブロッキング待ち:実行状態のスレッドは、wait()メソッドを実行して、スレッドをブロッキング待ち状態に移行させます。
    • 同期ブロッキング:スレッドは同期同期ロックの取得に失敗します(同期ロックが他のスレッドによって占有されているため)。
    • その他のブロッキング:スレッドのsleep()またはjoin()を呼び出してI / O要求が発行されると、スレッドはブロッキング状態になります。sleep()状態がタイムアウトになると、join()はスレッドの終了またはタイムアウトを待機するか、I / O処理が完了すると、スレッドは再び準備完了状態になります。
  • 死亡状況

    実行状態のスレッドがタスクを完了するか、他の終了条件が発生すると、スレッドは終了状態に切り替わります。

スレッドの優先度:

値の範囲は1(Thread.MIN_PRIORITY)-10(Thread.MAX_PRIORITY)です。

デフォルトでは、各スレッドには優先度NORM_PRIORITY(5)が割り当てられています。

スレッドの作成:

  • Runnableインターフェースを実装することにより、
  • Threadクラス自体を継承する。
  • CallableおよびFutureを介してスレッドを作成します。

1. Runnableインターフェースを実装する

class RunnableDemo implements Runnable {
    
    
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
    
    
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
    
    
      System.out.println("Running " +  threadName );
      try {
    
    
         for(int i = 4; i > 0; i--) {
    
    
            System.out.println("Thread: " + threadName + ", " + i);
            // 让线程睡眠一会
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
    
    
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
    
    
      System.out.println("Starting " +  threadName );
      if (t == null) {
    
    
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}
 
public class TestThread {
    
    
 
   public static void main(String args[]) {
    
    
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

演算結果:

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

2.スレッドを継承してスレッドを作成する

class ThreadDemo extends Thread {
    
    
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
    
    
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
    
    
      System.out.println("Running " +  threadName );
      try {
    
    
         for(int i = 4; i > 0; i--) {
    
    
            System.out.println("Thread: " + threadName + ", " + i);
            // 让线程睡眠一会
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
    
    
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
    
    
      System.out.println("Starting " +  threadName );
      if (t == null) {
    
    
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}
 
public class TestThread {
    
    
 
   public static void main(String args[]) {
    
    
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

演算結果:

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

スレッド方式

次の表は、Threadクラスのいくつかの重要なメソッドを示しています。

シリアルナンバー メソッドの説明
1 public void start()はスレッドの実行を開始し、Java仮想マシンはスレッドのrunメソッドを呼び出します。
2 public void run()スレッドが独立したRunnableオブジェクトを使用して構築されている場合は、Runnableオブジェクトのrunメソッドを呼び出します。それ以外の場合、メソッドは何もせずに戻ります。
public final void setName(String name)は、スレッド名を変更して、パラメーター名と同じにします。
4 public final void setPriority(int priority)は、スレッドの優先度を変更します。
5 public final void setDaemon(boolean on)は、スレッドをデーモンスレッドまたはユーザースレッドとしてマークします。
6 public final void join(long millisec)は、このスレッドの終了を最大でmillisミリ秒待機します。
7 public void interrupt()はスレッドに割り込みます。
8 public final boolean isAlive()スレッドが生きているかどうかをテストします。

スレッドがアクティブかどうかをテストします。上記のメソッドは、Threadオブジェクトによって呼び出されます。次のメソッドは、Threadクラスの静的メソッドです。

シリアルナンバー メソッドの説明
1 public static void yield()現在実行中のスレッドオブジェクトを一時停止し、他のスレッドを実行します。
2 public static void sleep(long millisec)現在実行中のスレッドを、指定されたミリ秒数以内にスリープ(実行を中断)しますこの操作は、システムタイマーとスケジューラの精度と精度の影響を受けます。
public static boolean holdLock(Object x)は、現在のスレッドが指定されたオブジェクトのモニターロックを保持している場合にのみtrueを返します。
4 public static Thread currentThread()は、現在実行中のスレッドオブジェクトへの参照を返します。
5 public static void dumpStack()は、現在のスレッドのスタックトレースを標準エラーストリームに出力します。

CallableおよびFutureを介してスレッドを作成します。

  • \ 1。Callableインターフェースの実装クラスを作成し、call()メソッドを実装します。call()メソッドはスレッド実行本体になり、戻り値を持ちます。
  • \ 2。Callable実装クラスのインスタンスを作成し、FutureTaskクラスを使用してCallableオブジェクトをラップします。FutureTaskオブジェクトは、Callableオブジェクトのcall()メソッドの戻り値をカプセル化します。
  • \ 3。ThreadオブジェクトのターゲットとしてFutureTaskオブジェクトを使用して、新しいスレッドを作成および開始します。
  • \ 4。子スレッドの実行が終了した後、FutureTaskオブジェクトのget()メソッドを呼び出して戻り値を取得します。

public class CallableThreadTest implements Callable<Integer> {
    
    
    public static void main(String[] args)  
    {
    
      
        CallableThreadTest ctt = new CallableThreadTest();  
        FutureTask<Integer> ft = new FutureTask<>(ctt);  
        for(int i = 0;i < 100;i++)  
        {
    
      
            System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
            if(i==20)  
            {
    
      
                new Thread(ft,"有返回值的线程").start();  
            }  
        }  
        try  
        {
    
      
            System.out.println("子线程的返回值:"+ft.get());  
        } catch (InterruptedException e)  
        {
    
      
            e.printStackTrace();  
        } catch (ExecutionException e)  
        {
    
      
            e.printStackTrace();  
        }  
  
    }
    @Override  
    public Integer call() throws Exception  
    {
    
      
        int i = 0;  
        for(;i<100;i++)  
        {
    
      
            System.out.println(Thread.currentThread().getName()+" "+i);  
        }  
        return i;  
    }  
}


匿名の内部クラスを使用してスレッドを作成します。

/*
 * 匿名内部类的格式:
 */
public class ThreadDemo {
    
    
    public static void main(String[] args) {
    
    
        // 继承thread类实现多线程
        new Thread() {
    
    
            public void run() {
    
    
                for (int x = 0; x < 100; x++) {
    
    
                    System.out.println(Thread.currentThread().getName() + "--"
                            + x);
                }
            }
        }.start();
        ;

        // 实现runnable借口,创建多线程并启动
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                for (int x = 0; x < 100; x++) {
    
    
                    System.out.println(Thread.currentThread().getName() + "--"
                            + x);
                }
            }
        }) {
    
    
        }.start();

        // 更有难度的,在Thread匿名内部类的里面再一次重写run方法
        //在实际运行时的结果是 hello+x。以thread的run方法为准。但是此处无意义
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                // TODO Auto-generated method stub
                for (int x = 0; x < 100; x++) {
    
    
                    System.out.println("java" + "--" + x);
                }

            }
        }) {
    
    
            public void run() {
    
    
                for (int x = 0; x < 100; x++) {
    
    
                    System.out.println("hello" + "--" + x);
                }
            }
        }.start();
    }
}

*免責事項:このブログ投稿は私の学習ノートです。新人チュートリアルやその他のネットワークリソースを参照してください。侵害されている場合は、プライベートメッセージを送信してください。*

おすすめ

転載: blog.csdn.net/qq_42380734/article/details/105387830