スレッド要約(1)

6534 ワード

ブログ参照
1.スレッド実装
  • はThreadクラス
  • を継承する.
  • Runnableインタフェース
  • を実装
    Runnableインタフェースを実現することは、Threadクラスを継承することよりも以下の利点がある:1.Java単一継承による限界を回避できる2.同じプログラムコードの複数のスレッド領域が統一リソースを処理するのに適している場合、すなわち共有リソースの処理
    2.スレッド割込み
  • は、interrupt() を使用してスレッドを中断し、スレッドが実行中である場合、別のスレッドは、ターゲットスレッドに中断されたことを示すフラグを設定し、すぐに戻るためにinterruptメソッドを呼び出します.
  • スレッドがsleep状態で他のスレッドによって中断するとInterruptedException異常
  • が放出される.
  • スレッドがinterruptメソッドを呼び出した後、スリープに遭遇するまで、InterruptedException
  • を放出する
    割り込み状態の判断:1.isInterrupetedインスタンスメソッド: .isInterrupted()を呼び出してスレッドの割り込みを確認し、スレッドが割り込まれた場合、メソッドはtrueを返し、フラグビットはクリアされませんが、sleepメソッドに遭遇した後、catchブロックの要約に入り、フラグビットがクリアされます.2.interrupted静的方法:Thread.interrupted()方法によって現在のスレッドの割り込み状態を検査し、現在のスレッドが割り込み状態にある場合、trueを返し、フラグビットを暗黙的にクリアし、すなわちfalseにリセットする.3.join方法:あるスレッドAで別のスレッドBのjoin方法を呼び出す場合、AスレッドはBスレッドの実行が完了してからjoinメソッドのコード4を実行するのを待つ.yieldスタティックメソッド:Thread.yield()メソッドを呼び出すと、同じレベル以上のスレッドにCPU実行権を譲り、CPUの実行権を待つ同じレベルのスレッドがなければ、そのスレッドは継続的に実行される
    3.スレッドの保留、リカバリと終了
  • 適切でないときにスレッドを一時停止すると、デッドロックやデータの不一致が発生する可能性があります.
  • は、フラグビットまたは待機通知を設定することによって、スレッドの保留およびリカバリのポリシーを実現する.不確実性を心配することなく、スレッドの指定された場所でスレッドの停止とリカバリを実現します.
  • 終端スレッドは、同様にフラグビットを適用する.

  • 4.デーモンスレッド
    Javaには、ユーザー・スレッドとデーモン・スレッドの2種類があり、デーモン・スレッドは他のユーザー・スレッドの実行にサービスを提供します.setDaemon(true)メソッドでスレッドをデーモンスレッドに設定します.注意点:1.setDaemon(true)は、スレッドのstart()メソッドを呼び出す前に設定する必要があります.2.デーモンスレッドで生成されたスレッドもデーモンスレッドに設定する必要があります.
    5.スレッドブロック
    スレッドがいつ中断されているか:1.スレッドがThread.sleep()を実行すると、指定された時間までブロックされるか、別のスレッドによって中断されます.2.スレッドがwait文式に遭遇すると、通知を受けるまでブロックされ、中断されるか、指定された時間が経過するまでブロックされます.3.InputStreamのreadメソッドやwriteメソッドなど、IO操作を行うとブロックされます.割り込み不可4.スレッドが他のスレッドによって占有されたロックを取得しようとすると、ブロックされ、割り込み不可
    6.volatile修飾子
  • 現在のJavaメモリモデルでは、スレッドは、メインメモリで直接読み書きするのではなく、ローカルメモリに変数を保存できます.これにより、データの不一致の問題が発生する可能性があります.この問題を解決するには、変数をvolatileとして宣言し、使用するたびにメイン内に読み取ります.
  • Java言語仕様では、最適な速度を得るために、スレッドが共有メンバー変数のプライベートコピーを保存することを許可し、スレッドが同期コードブロックに入ったり離れたりしたときにのみ、プライベートコピーを共有メモリの元の値と比較することができると指摘しています.volatileはJVMでのコード最適化を遮断しているため,効率的には低い.
  • JITまたはHotSpotコンパイラではserver client でコンパイルが異なり、serverモードではスレッドの実行を高速化するため、一方のスレッドが変数boolean flagの値を変更すると、もう一方のスレッドは見えなくなります.もう一方のスレッドは実行を高速化するためにレジスタまたはローカルcacheから値を取り、メモリから値を取るのではなく、レジスタまたはローカルcacheから値を取ります.ではvolatileを使用すると、どのスレッドでもvolatileで修飾された変数はメモリから値を取るように教えられます.
  • もし2つのスレッドがそれぞれvolatile変数を読み書きする時、スレッドAはあるvolatile変数を書き込み、スレッドBはこのvolatile変数を読み取る時、スレッドAのこのvolatile変数に対する書き込み操作を見ることができて、肝心なのはここで、それはこのvolatile変数に対する書き込み操作を見るだけではなくて、Aスレッドはvolatile変数を書く前にすべて見える共有変数を見ることができて、いずれもすぐにBスレッドに表示されます.

  • 7.synchronized修飾子
    同時プログラミングでは,マルチスレッドが同時に同時アクセスするリソースを臨界リソースと呼ぶ.synchronized修飾子を用いて実現される同期機構を反発ロック機構と呼び,得られるロックを反発ロックと呼ぶ
  • には、それぞれ独自のオブジェクトレベルロックがあります.スレッドがインスタンスオブジェクトのsynchronized同期コードブロックまたは同期方法にアクセスする場合、スレッドはインスタンスのオブジェクトレベルロックを取得する必要があります.他のスレッドがsynchronized同期コードブロックまたは同期メソッドにアクセスする場合、前のスレッドが同期コードまたはメソッドから終了するまで待機がブロックされます.
  • が1つのオブジェクトレベルのロックを持つことは、スレッドが交換(すなわちCPU実行権を失う)ことを阻止することはできず、他のスレッドが同じインスタンスのオブジェクトにアクセスする非synchronizedコード
  • をブロックすることもない.
  • クラスレベルロックは、staticメンバー変数およびstaticメソッドの同時アクセスを制御するために、特定のクラスのすべてのインスタンスによって共有される
  • .
  • synchronizedのロックメカニズムは再入可能な
  • である.
  • synchronizedのもう一つの機能:可視性を保証する
  • synchronizedとvolatileの違い:1.volatileは、volatile変数にアクセスする際にロックされない弱い同期メカニズムであるため、ブロックされない2.ロックは可視性と原子性を確保することができ、volatileは可視性を保証することができる3.以下の条件を満たす場合にのみvolatileを使用するべきである.1)変数への書き込み操作は変数の現在値に依存しない
    8.マルチスレッド環境でのコレクションの使用
    VectorとHashtableはスレッドが安全です.集合は本質的に非マルチスレッドで安全であり、複数のスレッドが集合と対話する場合、マルチスレッドを安全にするためには、追加の措置を取らなければならない.Collectionsには、同期メソッドによって非同期集合をカプセル化してスレッドセキュリティを達成する複数の静的メソッドがあります.
    public static Collection synchronizedCollection(Collection c)
    public static List synchronizedList(list l)
    public static Map synchronizedMap(Map m)
    public static Set synchronizedSet(Set s)
    public static SortedMap synchronizedSortedMap(SortedMap sm)
    public static SortedSet synchronizedSortedSet(SortedSet ss)
    
    
    /*
      ,ArrayList        ,        ArrayList     (         )。
    */
    /*          。            ArrayList  ,          。
    */
    List list = Collection.synchronizedList(new ArrayList());

    9.デッドロック
    スレッドAは現在、反発ロックlock 1を有し、スレッドBは現在、反発ロックlock 2を有している.次に、スレッドAがlock 1を保持している場合、スレッドBがlock 2を保持しているため、スレッドAは待機スレッドBによるlock 2の解放をブロックするlock 2を取得しようとする.このとき、スレッドBがlock 2を持っている場合にも、スレッドAがlock 1を持っているため、スレッドBは、A対lock 1の解放を待つのをブロックするlock 1を取得しようとする.どちらも相手が持っている鍵の解放を待っているが、どちらも自分が持っている鍵を解放していないので、両者はずっと詰まっている.この場合をデッドロックと呼ぶ.
    デッドロック回避:1、必要な最短時間でのみロックを保持し、同期方法全体の代わりに同期文ブロックを使用することを考慮する.2、同じ時刻に複数のロックを持つ必要がないコードをできるだけ作成し、避けられない場合は、スレッドが2番目のロックを持つ時間ができるだけ短いことを確保する.3、いくつかの小さなロックの代わりに大きなロックを作成し、使用し、このロックを単一のオブジェクトのオブジェクトレベルロックではなく、反発に使用します.
    10.再ロック可能
    ロックを取得する操作の粒度はスレッドです.再読み込みの実装方法の1つは、ロックごとにカウント値と所有者を関連付けることです.
    public class Father {  
        public synchronized void doSomething(){  
            //...
        }  
    }  
    
    public class Child extends Father {  
        public synchronized void doSomething(){  
            //... 
            super.doSomething();  
        }  
    }  

    同じスレッドは、このクラスの他のsynchronizedメソッド/ブロックまたは親クラスのsynchronizeメソッド/ブロックを呼び出すと、反発ロックが再入力可能であるため、スレッドの実行を阻害しません.