Javaの、ロックフリー同時実行の技術の問題を解決するには?どのように使用するには?

同期の使用に加えて、ロックが外にロックされ、Javaは、多くがある同時実行の問題をロックする必要はありませんツールを解決することができます

 

1、ツール原子

JDK 1.8では、クラスは、java.util.concurrent.atomicパッケージは、クラス原子は原子クラスがベースsun.misc.Unsafeが達成され、あります。

  • CPUの同時実行の問題を解決するために、CASはすなわち、比較と対話する、命令、フルネームの比較とスワップを提供します
  • CAS命令は三つのパラメータ、変数、比較値、新しい値が必要です。比較値は、変数の現在の値に等しい場合、変数は、その後、新しい値に更新されます
  • CASは、アトミック性を保証するためにCPUハードウェアレベルによってCPU命令であります
  • 原子には、java.util.concurrent.atomicパッケージ:オブジェクト参照型原子の基本データ型の原子、原子配列、原子オブジェクト属性および原子アキュムレータを更新します

AtomicBoolean、のAtomicInteger、AtomicLong:基本データ型の原子

オブジェクト参照の原子タイプ:AtomicReference、AtomicStampedReference、AtomicMarkableReference

アトミック配列:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

アトミック更新オブジェクトプロパティ:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater

アトミックアキュムレータ:DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder

 

簡単な例では、アトミック問題カテゴリの前のAtomicIntegerを使用することを我々のテストを変更します

パッケージconstxiong.concurrency.a026。

輸入java.util.concurrent.atomic.AtomicInteger。

/ ** 
 *测试原子类のAtomicInteger 
 * 
 * @author ConstXio​​ng
  * / 
パブリック クラスTestAtomicInteger { 

    // 计数变量
    静的な 揮発性のAtomicIntegerカウント= のAtomicInteger(0 ); 

    公共の 静的な 無効メイン(String []型引数)がスロー例外:InterruptedExceptionを{
         // 线程1给回数加10000 
        スレッドT1 = 新しいスレッド(() - > {
             のためにのInt J = 0; J <10 000; J ++ ){ 
                count.incrementAndGet(); 
            } 
            のSystem.out.printlnは( "スレッドT1は、10,000、カウントを終了" ;)
        );} 

        // 2 10000によってスレッド数 
        =スレッドT2 新しい新しいスレッド(() - > {
             ためINT J = 0; J <10 000; J ++ ){ 
                count.incrementAndGet(); 
            } 
            のSystem.out.println( "スレッドT2カウントプラス端10000" ); 
        }); 

        // スレッド1開始
        t1.startを();
         // スレッド2を開始します
        t2.start(); 

        // 1回の実行が完了したスレッドを待つ
        t1.join();
         // 実行2が完了したスレッドを待つ
        t2.joinを(); 

        // プリントカウント変数
        のSystem.out.println(count.get()); 
    } 

}

 

 

期待通りの結果を印刷

10000スレッドT2数プラス終了
スレッドT1回数プラス終了
 2万

 

 

2.スレッドローカルストレージ

  • java.lang.ThreadLocalクラスは、スレッドストレージをローカライズするために使用されます。
  • スレッドローカライズされたストレージは、このスレッドが唯一の変数の値を表示および変更することができ、各スレッドの変数を作成することです。
  • 典型的な例では、各スレッドの接続の接続のために別々のデータベースに格納されているにThreadLocalを使用して、データベース・トランザクションの問題に対処するスプリングを使用することです。
  • 使用していない、remove()メソッドを呼び出してください変数は、変数を削除するか、メモリリークの問題を引き起こす可能性があることに注意することにThreadLocalを使用してください。

 

パッケージconstxiong.concurrency.a026; 

/ ** 
 *のAtomicIntegerのテスト原子クラス
 * 
 * @author ConstXio​​ng
  * / 
パブリック クラスTestThreadLocal { 

    // スレッドローカルストレージ変数
    プライベート 静的 最終のThreadLocal <整数> = THREAD_LOCAL_NUM 新しい新しいのThreadLocal <整数> (){ 
        @オーバーライド
        保護整数はinitialValue(){ // 初期値
            戻り 0 ; 
        } 
    }; 

    公共 静的 ボイドメイン(文字列[]引数){
         ためINTを0 = I; Iは<3であり; Iは++){ // 3つのスレッド起動 
            スレッドT = 新しい新しいスレッドを(){ 
                @Override 
                公共 ボイドRUN(){ 
                    add10ByThreadLocal(); 
                } 
            }; 
            t.start(); 
        } 
    } 

    / * * 
     *プラスローカルストレージ変数をスレッド5。
     * / 
    プライベート 静的 無効add10ByThreadLocal(){
         試み{
             のためにint型 I = 0;私は<5;。私は++ ){ 
                Integer型N- = THREAD_LOCAL_NUM.get(); 
                N-+ = 1 ; 
                THREAD_LOCAL_NUM.set(N)
                System.out.println(にThread.currentThread()のgetName() + ":ThreadLocalのNUM =" + N)。
            } 
        } 最後に{ 
            THREAD_LOCAL_NUM.remove()。// 将变量移除
        } 
    } 
}

 

 

5の各スレッドプリントの最後の値

スレッド0:ThreadLocalのNUM = 1つの
スレッド -2:ThreadLocalのNUM = 1つの
スレッド -1:ThreadLocalのNUM = 1つの
スレッド -2:ThreadLocalのNUM = 2 
スレッド -0:ThreadLocalのNUM = 2 
スレッド -2:ThreadLocalのNUM = 3 
スレッド - 0:ThreadLocalのNUM = 3 
スレッド -1:ThreadLocalのNUM = 2 
スレッド -0:ThreadLocalのNUM = 4 
スレッド -2:ThreadLocalのNUM = 4 
スレッド -0:ThreadLocalのNUM = 5 
スレッド -1:ThreadLocalのNUM = 3 
スレッド -2: ThreadLocalのNUM = 5 
スレッド -1:ThreadLocalのNUM = 4 
スレッド -1:ThreadLocalのNUM = 5

 

 

3、コピーオンライト

  • コピーを書く必要は、遅延戦術の現れであると、英語名によると、見ることができます。
  • コピー・オン・ライトの容器の中にJavaが含まれます:CopyOnWriteArrayListと、CopyOnWriteArraySetを。
  • これは、フルボリュームコピーの配列を含み、それは、比較的メモリ消費、小さな書き込みの場合での使用に適しています。

 

簡単な例をCopyOnWriteArrayListと、ここではCopyOnWriteArrayListとの記述を使用する方法であり、スレッドセーフです。このシナリオでは、多くのあまりを読んで一度書くと、使用CopyOnWriteArrayListとは適していません。

パッケージconstxiong.concurrency.a026。

輸入はjava.util.ArrayList;
輸入はjava.util.List;
輸入java.util.Randomの。
輸入java.util.concurrent.CopyOnWriteArrayList。

/ ** 
 *测试コピー・オン・ライト
 * @author ConstXio​​ng
  * / 
パブリック クラスTestCopyOnWrite { 

    プライベート 静的 最終ランダムR = 新しいランダム(); 
    
    プライベート 静的 CopyOnWriteArrayListと<整数> cowList = 新しい CopyOnWriteArrayListと<整数> ();
//    =新しい新しいcowList ArrayListの静的プライベート<整数>のArrayList <Integer型>(); 
    
    公共の 静的な 無効メイン(文字列[] argsが)スローInterruptedExceptionある{ 
        一覧 <スレッド> =スレッドリストの新しい新しいのArrayList <スレッド> ();
         // スレッド1000を起動し、 cowList 5のランダムな整数に
        のためにint型 ; IはI = 0 <1000;私は++を){ 
            スレッドT = 新しい新しいスレッド(() - > {
                 のためにint型 J = 0; J <5; J ++ ){
                     // スリープ10 、cowListに整数を追加しているスレッドが同時実行の問題につながるように、MS、
                    してみてください {
                        Thread.sleep( 10 )。
                    } キャッチ(InterruptedExceptionある電子){ 
                        e.printStackTrace(); 
                    } 
                    cowList.add(R.nextInt( 100 ))。
                } 
            })。
            t.start(); 
            threadList.add(T)。
        } 
        
        のための(スレッドT:スレッドリスト){ 
            t.join()。
        } 
        のSystem.out.println(cowList.size())。
    } 
}

 

印刷結果

5000

 

 

もし

プライベート 静的 CopyOnWriteArrayListと<整数> cowList = 新しい CopyOnWriteArrayListと<整数>();
変更
プライベート 静的 ArrayListに<整数> cowList = 新しいのArrayList <Integer型>();
 

印刷結果は整数5000未満であります


       


Javaのインタビューの質問の概要は、いつもあなたが立ち往生しています!

 

おすすめ

転載: www.cnblogs.com/ConstXiong/p/11688011.html