ダークホースプログラマー——Java基础---マルチスレッド

10221 ワード

ダークホースプログラマー——Java基础---マルチスレッド
 
------ Javaトレーニング、Androidトレーニング、iOSトレーニング、Netトレーニング 交流することを期待しています。
 
一、概要
Javaに対しては、複数のスレッドが1つのプログラムで同時に起動され、これらのスレッドが複数のプロセッサで同時に実行されるようにすることができる。単一プロセッサシステムでは、複数のスレッドがCPU時間を共有することを時間共有といい、一方、オペレーティングシステムは、単一プロセッサであっても、マルチスレッドプログラムの実行速度は、単一スレッドプログラムよりも速い。      プログラムがアプリケーションとして実行される場合、少なくとも1つのスレッドがあります。それはJava仮想マシンがメインスレッドとして、Mainメソッドで起動するスレッドです。Java言語は非常に優れたマルチスレッドサポートを提供しており、プログラムは非常に簡単な方法でマルチスレッドを起動することができます。以下では、作成スレッド、起動スレッド、制御スレッド、およびスレッドの同期動作について詳細に説明する。
 
二、本文
1、スレッドの作成と起動
1.1 Thread類を継承してスレッド類を作成する
Threadクラスを継承してマルチスレッドを作成する手順は以下の通りです。
  • は、Threadクラスのサブクラスを定義し、このタイプのrun()方法を書き換える。
  • は、Threadサブクラスの例を作成し、スレッドオブジェクトを作成した。
  • は、スレッドオブジェクトのstart()方法を起動してスレッドを起動する。         
  • 次のセクションは、Threadスレッドを作成するコードです。
    class Test extends Thread {
    
    
    
        String name;
    
    
    
        public TimePrinter(String name) {
    
    
    
            this.name = name;
    
    
    
        }
    
    
    
           //  run  
    
    
    
        public void run() {
    
    
    
           //       
    
    
    
                         System.out.print(name);
    
    
    
        }
    
    
    
           }
    
    
    
       
    
    
    
           class ThreadTest{
    
    
    
           static public void main(String args[]) {
    
    
    
            //  teat  ,     
    
    
    
                  Test test = new Test("zhang");
    
    
    
                  test.start();
    
    
    
        }
    
    
    
    }
    この例では、Threadスレッドの作成方法を簡単に紹介しますが、スレッドとして実行されるクラスは、あるタイプのサブクラスであり、Threadを継承することによってスレッドを作成することができません。javaは単に継承するだけですので、この場合は、Runnableインターフェースを使用しなければなりません。
     
    1.2 Runnableインターフェース作成スレッドクラスを実現する
          Runnableインターフェースを実現してマルチスレッドを作成して起動するステップは以下の通りです。
  • は、Runnableインターフェースの実装クラスを定義し、このインターフェースのrun()方法を書き換える。
  • は、Runnable実装クラスの例を作成し、この例をThreadのインスタンスを作成するパラメータとして
  • に入力する。
    以下はRunnableインターフェースを実現してスレッドコードを作成します。
    class Test implements Runnable {
    
    
    
        String name;
    
    
    
        public TimePrinter(String name) {
    
    
    
            this.name = name;
    
    
    
        }
    
    
    
           //  run  
    
    
    
        public void run() {
    
    
    
           //       
    
    
    
                         System.out.print(name);
    
    
    
        }
    
    
    
           }
    
    
    
       
    
    
    
           class ThreadTest{
    
    
    
           static public void main(String args[]) {
    
    
    
            //  teat  ,      Thread     ,  Thread  r    
    
    
    
                  Test test = new Test("zhang");
    
    
    
                  Thread r = new Thread(test);
    
    
    
                  r.start();
    
    
    
        }
    
    
    
    }
    注:runnableインターフェースを使用すると、必要なクラスのオブジェクトを直接作成して実行することはできません。Threadクラスの例の中から実行しなければなりません。多くのプログラマは、Threadクラスから引き継ぐとクラスを強制するので、runnableインターフェースがもっと好きです。
     
    2、スレッドのライフサイクル
          スレッドが作成されて起動されると、新規作成、準備、運転、ブロッキング、死亡の5つの状態を通ります。すなわち、
  • 新規作成(new):newスレッドがあると、このスレッドは新規作成された状態になり、Javaオブジェクトと同じで、Java仮想マシンだけがメモリ空間を割り当て、メンバ変数を初期化する。この時スレッドオブジェクトはダイナミックな特徴を示さず、プログラムもスレッドの実行体を実行しない。
  • 準備完了(Keady):スレッドは実行できますが、利用可能なプロセッサを待っています。起動したばかりか、ブロックから回復したばかりか、あるいは他のスレッドに奪われました。
  • 実行(Kunning):スレッドが動作しています。マルチプロセッサシステムでは、複数のスレッドが動作している可能性があります。
  • ブロッキング(Blocked):スレッドは、「プロセッサ」以外の他の条件のために実行できません。条件変数の変化、インターロックをかけたり、I/O動作が終了するのを待ったりします。
  • 終了(Terminated):スレッドは起動関数から戻り、またはpthreadauexitを呼び出し、またはキャンセルされ、自分自身を終了し、すべてのリソースのクリーンアップ作業を完了します。分離されているわけではなく、接続されているわけでもありません。分離されたり、接続されたりすれば、回収されます。
    Thread類とこれらの4つの状態に関する方法を以下に示します。
    //     
    
    
    
    publicvoid start( ); 
    
    
    
    publicvoid run( ); 
    
    
    
    //        
    
    
    
    publicstaticvoid sleep(long millis); 
    
    
    
    publicstaticvoid sleep(long millis, int nanos); 
    
    
    
    publicvoid resume( ); //  
    
    
    
    publicvoid suspend( );  //  
    
    
    
    //     
    
    
    
    publicvoid stop( );  //  
    
    
    
    publicvoid interrupt( ); 
    スレッドは、作成直後にrunメソッドのコードを実行するのではなく、待機状態にあります。スレッドが待機状態にある場合は、スレッドの優先度、スレッド名、スレッドのタイプなど、様々な属性を設定することができます。
          startメソッドを起動すると、スレッドはrunメソッドのコードを実行し始めます。スレッドは実行状態に入ります。Thread類のisAlive方法でスレッドが運転状態にあるかどうかを判断できます。スレッドが動作状態にある場合、isAliveはtrueに戻ります。isAliveがfalseに戻ると、スレッドが待機状態になる可能性があります。以下のコードはスレッドを示します。の作成、運転、停止の3つの状態の切り替えを行い、対応するisAlive戻り値を出力します。
          スレッドが起動すると、このスレッドは終了します。しかし、スレッドが実行されている間は、スレッドを一時停止させることができます。この2つの方法はsuspendとsleepです。suspendを使ってスレッドを切った後は、reume方法でスレッドを起動することができます。また、sleepを使ってスレッドを休止させた後は、設定されたスレッドのみが起動されます。の時間後にスレッドを準備状態にします。(スレッドが休止してから、スレッドがすぐに実行されるとは限りません。準備状態に入って、システムのスケジュールを待っています。)
     
    3、スレッド同期
          システムスレッドスケジュールは一定のランダム性を持っているので、「エラー」が発生しやすくなり、安全問題になります。この問題を解決するために、jaaマルチスレッドは同期コードブロックの概念を導入しています。具体的な文法は以下の通りです。
    synchronized (obj){
    
    
    
           //            
    
    
    
    }
    同期コードブロックに対応する同期方法、すなわち、synchronizedキーを用いて、ある方法を修飾すると、この方法は同期方法と呼ばれています。同期方法を使用することにより、スレッドセキュリティのクラスが非常に容易に実現されます。具体的な特徴は以下の通りです。
  • クラスのオブジェクトは、複数のスレッドによって安全にアクセスできます。
  • 各スレッドがオブジェクトの任意の方法を呼び出した後、正しい結果が得られる。
  • 各スレッドがオブジェクトの任意の方法を呼び出した後も、オブジェクトの状態は依然として合理的な状態を維持している。
    以下は具体的な文法です。
    public void method3(SomeObject so) {
    
    
    
           synchronized(so)
    
    
    
    {
    
    
    
         //…..     
    
    
    
    }
    
    
    
    }
    注意:synchronizedキーを使用する場合は、synchronizedメソッドやsynchronizedブロックでsleepまたはyieldメソッドを使用することはできるだけ避けなければなりません。synchronizedプログラムブロックが対象錠を占有していますので、休憩は他のスレッドがあなたの目覚めを待って実行されます。
    同様に、同期プログラムブロック内でyeildメソッドを呼び出してCPUリソースを譲ることも意味がない。あなたがロックを使っているため、他の相互反発スレッドはまだ同期プログラムブロックにアクセスできない。もちろん、同期プログラムブロックに関係のないスレッドはより多くの実行時間を得ることができる。
     
    4、スレッド通信
          スレッド間では同期の他に、通信も考えられます。Java 5の前の通信方式は、waitとnotifyです。それではCoditionの利点は、多重待ち時間をサポートすることです。つまり、私は複数のCoditionを定義できます。各conditionコントロールスレッドの実行通路を定義できます。伝統的な方法は、一緒に待つしかありません。Java 5 Appのバッファキューの実現を分析してみます。:
    バインディングされたバッファがあると仮定して、サポートします。 put 和 タカ 方法です。空いているバッファでtake操作をしようとすると、あるアイテムが利用可能になる前にスレッドがブロックされてしまいます。満杯のバッファでput操作をしようとすると、スペースが使えるようになる前にスレッドがブロックされてしまいます。単独でsetを保存するのが好きです。 スレッドとtake スレッドは、このようにして、バッファ内のアイテムや空間が利用可能になったときに、最適な企画を利用して、一回に1つのスレッドだけを通知することができます。この点は、2つのconditionのインスタンスを使用して行うことができます。
    4.1 condition制御スレッド通信を使用する
    プログラムがsynchronizedキーを使用しないで同期を保証し、直接にLockオブジェクトを使用して同期を保証すると、システムには暗黙的な同期モニタが存在しないので、wait()、notify()、notifyAll()方法でスレッド通信ができなくなります。
    ロックオブジェクトを使用して同期を保証する場合、Javaはconditionクラスを提供して協調を維持し、conditionオブジェクトを使用してロックオブジェクトを取得しても実行できないスレッドをロックオブジェクトを解放し、conditionオブジェクトは他の待ちスレッドを起動することができる。
    Condationの例はロックオブジェクトに結び付けられています。特定のLockインスタンスのconditionの例を得るためには、ロックオブジェクトのnewConditionを呼び出す方法があります。Coditionクラスは、await()、signal()とsignal All()の3つの方法を提供しています。
     
    4.2ブロック列を使用してスレッド通信を制御する
    ブロック列は、生産者スレッドがブロックキングQueに要素を入れようとすると、列がいっぱいになったら、スレッドがブロックされます。消費者スレッドがブロックキングQueから要素を取り出しようとすると、列が空になったら、スレッドがブロックされます。
    プログラムの2つのスレッドは、ブロックQueに要素を交互に入れることで、スレッドの通信をうまくコントロールすることができます。BlockingQueは、ブロックをサポートする2つの方法を提供します。
     
    三、まとめ
    本論文では主にマルチスレッドを作成して起動する方法を紹介し、2つのマルチスレッド方式の間の利点と劣勢を説明し、スレッドのライフサイクルを比較的詳細に紹介し、スレッド同期方法を簡単に説明し、最後に2つの回線通信を実現する方法を紹介します。これらはすべてマルチスレッドを学ぶための基本的な知識です。