Javaの一般的な知識の概要(⑬) - スレッド

Javaの組み込みサポートを提供するために、プログラミング、マルチスレッド。スレッドは、プロセスシーケンスの単一の制御フローを参照して、プロセスは、並行して、各スレッドは、異なるタスクを実行するために、複数のスレッドによって複雑にすることができます。

マルチスレッドは、マルチタスク、マルチスレッドの特別な形態であるが、より小さなリソースのオーバーヘッドを使用します。

他の用語は、本明細書に定義され、関連するスレッドれる - プロセス:1つ以上のスレッドを含むオペレーティング・システムによってメモリ空間の割当てを含む方法。別のスレッドが存在しないことができ、それはプロセスの一部でなければなりません。プロセスは、非デーモンスレッドの全てが完成し実行している後までに終了し、実行されています。

マルチスレッドは、CPUをフルに活用を達成するための効率的なプログラムを書くためにプログラマーを満たすことができます。

ライフサイクルのA. Aスレッド

スレッドには、それはまた、死への作成からプロセスがあり、実行の動的なプロセスです。

新しい状態は:スレッドオブジェクトと新しいキーワードThreadクラスまたはサブクラスを確立した後、スレッドは、オブジェクトの新しい状態です。これは、プログラム開始()このスレッドになるまでこの状態のままになります。

**レディ状態:**スレッドオブジェクトがstart()メソッド、準備完了状態にスレッドを呼び出します。レディキューで準備完了スレッドは、JVMのスレッドスケジューラをスケジュールする待っています。

動作状態:スレッドがCPUリソースの準備状態を取得した場合、あなたが実行を行うことができます()、スレッドがこの時点で実行されます。最も複雑を実行中のスレッド、それがブロックされた状態、レディ状態、および死の状態になることができます。

ブロッキング状態:スレッドがスリープ状態(スリープ)の後に実行された場合は、(保留)中断し、他の方法は、占有リソースの損失は、スレッドが実行されているからブロックされた状態になります。睡眠時間では機器やリソースがレディ状態を再入力することがあり得るようになってきました。これは3つのタイプに分けることができます:

  • ブロックを待っている:実行スレッドが待ちの状態()メソッドを実行し、スレッドは状態に入るのを待ってブロックされています。
  • 同期ブロック:(別のスレッド同期ロックが占有されているため)同期スレッド同期ロックの失敗を取得します。
  • 他のブロッキング:I / O要求を発行し、スレッドが()を呼び出すスレッドの睡眠を(ブロックすることにより、状態に入る)か、参加します。睡眠()タイムアウト、終了するスレッドの参加()待機またはタイムアウト、またはI / O処理が再びレディ状態に、スレッドを終了しました。

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

Thread.run()およびThread.start()との差

  • スレッドを開始する()メソッド、真のマルチスレッド動作を開始します。そして、完成されたrunメソッド本体のコードを待たずに、次のコードに直接進むことができ、開始Threadクラス()メソッドを呼び出すことにより、スレッドを開始し、その後、このスレッドは準備完了状態にあり、実行されていません。そして、このメソッドは、このスレッドの内容は終了し、このスレッドを実行するために、Runメソッドを終了し、実行することが含まれているメソッドの実行は、()スレッド体と呼ばれ、その実行動作が、完了するためにThreadクラスの実行を()を呼び出します。その後、CPUは他のスレッドを再スケジュール。
  • 道の定期的な方法として、run()メソッドを呼び出します。次のコードを続行するために、その実装後に実行する方法を待つ、手順又は順序を実行するために、このプログラムを、唯一のメインスレッドが唯一のプログラムの実行パスであるスレッドであるので、書き込みスレッドへの目的はありません。

II。睡眠と待ち時間の違い

Threadクラスから睡眠、待機からObjectクラス:これらの2つの方法は、異なるカテゴリからです。睡眠は、スレッドがBさんを呼び出すコードで睡眠を寝bのスレッドで睡眠の呼び出し方法bが、実際には、まだ眠りにつくが、聞かせていても、ベッドに行く人と呼ばれるスレッドの静的メソッドです。

ロック:睡眠は、他のスレッドが使用されるか、または同期制御ブロックの方法することができるように、ロック、ロック解除待ち方法を解放していない最も重要な方法です。**睡眠システムリソースを販売しないように、待ち時間がシステムリソースを待ってみましょうするスレッドプールに入るのを待っている、他のスレッドがCPUを占有することができます。**通常は、リソース待機スレッドが十分ではありません実行されるので、制限時間は増えません待って、他のスレッドの呼び出しを待つことは無駄である/のnotifyAllは、OSディストリビューションシステムを待っているレディキューに入りますアッププールで待機しているすべてのスレッドをスリープ解除通知資源。それは自動的に目を覚ますように、スリープ(ミリ秒)以下の割り込みよりも()強制的に中断された場合にのみ呼び出すことができ、時間を指定することができます。役割のThread.sleep(0)され、「オペレーティングシステムは、すぐに再CPUの競争をトリガします。」

範囲:待機、通知、および同期またはブロックを制御するためのnotifyAllのみ同期制御方法(同期)それに使用されるが、使用任意の場所スリープすることができます。

   synchronized(x){ 
      x.notify() 
     //或者wait() 
   }
复制代码

優先III。スレッド

各Javaスレッドは、オペレーティングシステムのスレッドスケジューリング順序を決定するのに役立ちます優先順位を持っています。

10(Thread.MAX_PRIORITY) - Javaスレッドの優先度は1(Thread.MIN_PRIORITY)の範囲の整数です。

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

優先度の高いスレッドはプログラムにとってより重要である、と前に優先順位の低いスレッドにプロセッサリソースを割り当てる必要があります。しかし、注文は実行のスレッドの優先順位のスレッドを保証するものではありませんが、また、プラットフォームに非常に依存。

IV。スレッドの作成

Javaはスレッドを作成するには、3つの方法が用意されています。

  • 、Runnableインタフェースを実装することにより、
  • 継承Threadクラス自体を通じ、
  • 呼び出し可能と未来を通じてスレッドを作成します。

、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();
   }   
}
复制代码

継承Threadクラス自体を通じ

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();
   }   
}
复制代码

呼び出し可能と未来を通じてスレッドを作成します。

  • 実行、および戻り値のスレッドとして呼び出し可能インタフェースの実装クラスを作成し、器具()メソッドの呼び出し、呼び出し()メソッド。
  • ()メソッドの呼び出しの戻り値のFutureTask呼び出し可能オブジェクトをカプセル化するオブジェクトパッケージ呼び出し可能FutureTaskクラスオブジェクトを使用して、実装クラスのインスタンスを作成して呼び出し可能。
  • ターゲット・オブジェクトとして使用FutureTaskスレッドオブジェクトが作成し、新しいスレッドを開始します。
  • コール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;  
    }  
}
复制代码

スレッドを作成するための3つの方法の比較

  • Runnableを、呼び出し可能インターフェース手段、Threadクラスの実装、Runnableインタフェースまたは単に呼び出し可能インターフェースを実現するために複数のスレッドを作成して使用する場合、あなたはまた、他のクラスから継承することができます。
  • あなたは、準備するための簡単なマルチスレッド使用の継承Threadクラスを作成するときは、現在のスレッドにアクセスする必要がある場合、あなたは現在のスレッドを取得するためにThread.currentThread()メソッド、直接使用これを使用する必要はありません。

いくつかの主要な概念V.スレッド

マルチスレッドプログラミングでは、次の概念を理解する必要があります。

  • スレッド同期
  • スレッド間通信
  • スレッドのデッドロック
  • スレッド制御:一時停止、停止と再開

VI。マルチスレッドの使用

マルチスレッドの有効活用の鍵は、プログラムを理解することで同時に実行ではなく連続的に実行されます。たとえば:2つのサブプログラムが同時実行を必要としますが、マルチスレッドプログラミングの利点を取る必要があり、この時があります。

複数のスレッドを使用することにより、あなたは非常に効率的なプログラムを書くことができます。しかし、あなたはあまりにも多くのスレッドを作成した場合、プログラムの実行の効率が実際に減少し、よりもむしろ増強されることをメモしてください。

コンテキストの切り替えは、オーバーヘッドあなたはあまりにも多くのスレッドを作成した場合、CPU時間は、プログラムの実行よりもコンテキストスイッチング時間に費やし、また非常に重要であり、覚えておいてください!

おすすめ

転載: juejin.im/post/5e64eb896fb9a07cc10ab03e