Javaのマルチスレッドのインタビューの知識Liteの

ディレクトリ

 

マルチスレッド

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

Q:どのようにマルチスレッド理解してください

スレッド間通信

ロック

揮発性

ThreadLocalの

スレッドプール

そして、請負ツール

プログラミングの問題


マルチスレッド

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

新 - レディ - ランニング - ブロックされた - 準備 - 実行 - 死

 

 

Q:どのようにマルチスレッド理解してください

  1. 定義:マルチスレッドは、ソフトウェアやハードウェアから複数のスレッド技術の同時実行を実現するために参照します。マルチスレッド機能を備えたコンピュータによるハードウェアサポートにし、それによって全体の処理性能を向上させる、同時に一つのスレッド以上を実行することができます。
  2. その理由は存在しますが低いため、シングルスレッドの処理能力の。類推、男数人Quban Qubanレンガとレンガ、人が唯一の車を移動することができますが、少数の人々が複数の車両を同時に動かすことができますが。
  3. 実装:スレッドを実装する方法、スレッド、Runnableを、Javaで呼び出し可能。
  4. 質問:スレッドより高いスループットを達成することができ、スイッチのスレッドに必要なスレッドスタックスペースのが大きなコスト、時間、サイズ、スレッドプールを使用するので、繰り返し使用、それは作成しないように、スレッドプールにスレッドバックを使用して終了しますそして、オーバーヘッド破壊。

スレッド間通信

  1. )(中断)(参加)(通知)(通知メカニズム待ちを待ち
  2. 同期同時ツール、ロック、たCountDownLatch、CyclicBarrierを、セマフォ

ロック

ロックとは何ですか

ロックは、同期制御ツールダウン、とだけ他のスレッドが終了するのアクセスにロック、または待機をスレッド同期コードを取得した後にリソースの競合のロックを解除する別のスレッドを実行するスレッドの場合には別の方法が割り当てられています

同期

通常のnotifyAll 1つの使用、通知、待ちます。
待機:オブジェクトロックの所持が解除され、待機キューにCPUのリリースでは、唯一の通知/すべてを糸を続けることができます。
睡眠:それはCPUのリリースですが、スレッドの睡眠の終了後も継続自動的にオブジェクトのロックの所有権を解放しません。
通知:そう訪問のためのロックを取得し、キュー内で待機しているスレッドを覚まします。
notifyAll:競争がロックを取得してみましょう、このロックのキュー待ちに待っているすべてのスレッドを覚まします。

ロック

同じセマンティクスを同期するが、時間ロックを待って待って、このような割り込みロックなど、いくつかの他の機能を追加するので、ロックではなく、同期の使用できますが、ロックが解除され、手動でロックする必要がありました

両者の違い

  • パフォーマンス:;リソースのためではない熾烈な競争が、両者のパフォーマンスがほぼ同じであれば激しい資源競争の下では、ロックのパフォーマンスが同期より良くなります
  • 使用方法:コードの同期ブロックは、方法を使用することができます。コード実装によってロックが、スレッドのより正確な意味論があるが、手動でも、フェアロックとして、同期のさまざまを提供解放する必要性が、同期の時間制限があり、同期が中断されていてもよいです
  • 原理は:達成するために、JVMレベルで同期され、追加されますmonitorenter monitorexitバイトコード生成、任意のオブジェクトは、それをモニターし、開催された後、モニタが関連付けられている、彼はロックされます。監視JVMは、メモリ・バリア・コマンドで共有さらに変数の視認性を確保するために、同期、同期ツールです。使用AQSで達成ロックコードレベルは、オペレーティングシステムカーネルにUnsafe.park呼び出しによってブロックされました
  • 機能:例えば、より強力なReentrantLockの
    1. ReentrantLockのが公正または不当なロックロックするかどうかを指定しますが、唯一の非同期フェアロックすることができ、いわゆるフェアロックはロックを取得するためのスレッドを待つことです
    2. ReentrantLockのはないように、実装のスレッドがウェイクアップウェイクアップする必要がグループ化されているという条件(条件)クラスを提供し、同期またはすべてのスレッドまたはスレッドまでランダムウェイクを覚まします
    3. ReentrantLockのロックを待っているスレッドを中断することができるメカニズムを提供する、この機構)(lock.lockInterruptiblyによって実現されます

私たちは同期を書くとき、優先順位は、あなたは特別なニーズを持っている場合、同期した後、さらに最適化されました。アトミックReentrantLockのとパフォーマンスは向上しませんが、また、災害につながる可能性だけでなく、不適切に使用されます。

ロックの種類

  • ロックフェア/不公平ロック

フェアは、ロックを取得するために複数のスレッドを適用するために手段をロックラッチ
ReentrantLockのがコンストラクタかどうかを指定フェア、フェアデフォルト以外のロックであるロックラッチ。同期は非ロック公平です

  • リエントラントロック

ロック時にメソッドの外層を取得インナーロックに入る、方法は自動的になります同じスレッドを指し
ReentrantLockの、彼の名前は、名前が再入ロックでロック再入力リエントラントロック、ことが見られることができ
、また、同期をリエントラントロック。利点の一つは、リエントラントロックすることができ、デッドロックを避けるために、ある程度までです

  • 排他ロック/共有ロック

排他ロックは、ロックが唯一のスレッドが保持できることを意味します。共有ロックは、ロックが複数のスレッドによって保持することができることを意味
ReentrantLockの排他的ロックです。しかし、ロックは排他書き込みロックをロック共有読んでロックされ、他の実装クラスReadWriteLockロック、ためである
共有の読み取りロックロック書き込みプロセスが相互にある、読んで、書き込み、読み込み、非常に効率的な同時読み取りを確保することができます除外
同期は排他ロックです

  • 楽観/悲観的ロックをロック

ロックのさまざまな方法を使ってJavaで悲観的ロックは
、Javaで使用楽観的ロックCAS、典型的な例は、原子基づいて、アルゴリズムは、アトミック操作は、スピンCAS更新することによって達成されます

  • 偏ったロック/ロック軽量/ヘビー級ロック

同期ロック状態の場合:
バイアスロックはロックの使用の場合には非競争とスレッドを1つだけ減らすことです、ロックは、消費の軽量パフォーマンスを使用して製造しました。同期コードの期間を指す全体同期競合の不存在下で、スレッドによってアクセスされているが除去される
軽量ロックが実際の競争の欠如を低減することで、使用することは、ヘビーロックパフォーマンス・オーバーヘッドを生成します。ロックが別のスレッドによってアクセスされ、それは軽量バイアスロックロックにアップグレードされる場合、別のスレッドがCASスピンの形でロックを取得しようとロッキングフィンガを付勢されている場合、ブロックしない
ことと、ロックヘビーロック手段を別のスレッドはしかしスピンですが、軽量ロックのようにスピンない最後の永遠意志、特定の回数は、まだロックを取得していないスピンは、ブロックに入り、ロックインフレヘビー級ロック

  • スピンロック/適応スピンロック

ロックを獲得する試みが直ちに遮断されないスレッドを指し、代わりにロックを取得しようとする循環方式を使用する、この利点は、スレッドコンテキストスイッチの消費を低減することであり、欠点は、サイクルはCPUを消費することで、デフォルト数は10回転で
適応スピンスピンロックは、もはや一定の回数ではありませんが、スピンロックの時間と元の決定の所有者とロックされた状態で一度は、予測因子仮想マシンロック状態であります

揮発性

特長:

  1. メモリとメインメモリを協力して、メインメモリは読み取りおよび書き込み操作は、視認性を確保するために、直接対話に生成されます。
  2. JVMの命令の並べ替えを禁止します。

ThreadLocalの

使用ThreadLocal<UserInfo> userInfo = new ThreadLocal<UserInfo>()方法ので、各々が雌ねじThreadLocalMapを維持することは、内部エントリ(KVキーと値のペア)の数が含まれ、それぞれが第一現在のスレッドIDへのアクセスを取得し、次にスレッドオブジェクトマップを取得し、その後、地図相互作用。

スレッドプール

起源

新しいスレッドの欠点:

  • あなたは新しいスレッドを起動するたびに新しいThreadオブジェクトのスレッド、パフォーマンスの低下を必要とします。スレッドプール内のスレッドは、オブジェクトの作成、オーバーヘッドの回復を減らし、再利用することができます。
  • 一元管理の欠如を通し、あなたがOOMを結果として、新しいスレッドを制限することができます。あなたは、スレッドプールは、実行の同時スレッドの最大数を作成することができます制御することができます。
  • 技術的手法の欠如など定期的な実行スレッドの割り込みなどの一部の高度な機能。スレッドプールは、同時制御の数を定期的に提供しました

ときにコアスレッドプールのパラメータ

  • corePoolSize:スレッドのコア数の数、スレッドプールのスレッドが永続的でなければなりません
  • maximumPoolSize:タイムアウトがクリアされた後にスレッドプール内のスレッドの最大数は、非コアスレッドを可能にします
  • ワークキュー:実行されるのを待っているタスクの待ち行列をブロックが格納されます
  • keepAliveTimeが:スレッドを保持することが可能なタスクを実行する時間がありません。
  • 単位:時間の単位
  • threadFactory:スレッドファクトリ、スレッドを作成します
  • rejectHandler:拒否の方針は、タスクを提出する際に(例外をスロー、呼び出し側とミッションのスレッドが現在のタスクキューの最初のタスクの実行を破棄、配置され、タスクを破棄)

論理スレッドを作成します。

次のタスクは、ThreadPoolExecutor.executeメソッドからロジックをコミットします。

  1. スレッドの数が<corePoolSizeを実行している場合は、直接他のスレッドがアイドル状態であっても、新しいスレッドを作成
  2. 実行中のスレッドの数> = corePoolSize場合は
    成功した場合は2.1がキューに挿入され、このタスクの完了を提出しますが、新しいスレッドを作成しない
    2.2あなたは、キューを挿入すると失敗し、キューがいっぱいになった
    現在のカウント<maximumPoolSize、スレッドが新しいスレッドを作成する場合2.2.1スレッドプールに
    2.2.2スレッドの現在の数は> = maximumPoolSizeは、指定したポリシーを実行することを拒否する場合は

ブロッキングキュー戦略

  • 直接提出。SynchronousQueueはBlockingQueueのバッファのデータはありませんが、挿入は、消費者が操作テイクを削除するのを待つ必要があり、その生産者スレッドを置きます。タスクは、それらを維持するのではなく、スレッドに直接提出しました。
  • アンバウンド形式のキュー。無制限maximumPoolSizesを使用する場合は、すべてのcorePoolSizeスレッドがビジー状態のとき、それはキューで待機して新しい仕事につながります。
  • 有界キュー。限定maximumPoolSizesを使用する場合、(例えばArrayBlockingQueueなど)有界キューは、リソースの枯渇を防ぐのに役立ちますが、調整及び制御することが困難であってもよいです。

そして、請負ツール

たCountDownLatch

閉鎖症は、カウンタが実行し続けるために、一定の条件の下で、メインスレッドを満たすためにメインスレッドなので、他のスレッドのスレッド同期ツールをブロックすることができます。

 

图中,A为主线程,A首先设置计数器的数到AQS的state中,当调用await方法之后,A线程阻塞,随后每次其他线程调用countDown的时候,将state减1,直到计数器为0的时候,A线程继续执行。

使用场景:
并行计算:把任务分配给不同线程之后需要等待所有线程计算完成之后主线程才能汇总得到最终结果
模拟并发:可以作为并发次数的统计变量,当任意多个线程执行完成并发任务之后统计一次即可

Semaphore

信号量是一个能阻塞线程且能控制统一时间请求的并发量的工具。比如能保证同时执行的线程最多200个,模拟出稳定的并发量。

public class CountDownLatchTest {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(3); //配置只能发布3个运行许可证
        for (int i = 0; i < 100; i++) {
            int finalI = i;
            executorService.execute(() -> {
                try {
                    semaphore.acquire(3); //获取3个运行许可,如果获取不到会一直等待,使用tryAcquire则不会等待
                    Thread.sleep(1000);
                    System.out.println(finalI);
                    semaphore.release(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }
}

由于同时获取3个许可,所以即使开启了100个线程,但是每秒只能执行一个任务

使用场景:
数据库连接并发数,如果超过并发数,等待(acqiure)或者抛出异常(tryAcquire)

CyclicBarrier

可以让一组线程相互等待,当每个线程都准备好之后,所有线程才继续执行的工具类

 

 

与CountDownLatch类似,都是通过计数器实现的,当某个线程调用await之后,计数器减1,当计数器大于0时将等待的线程包装成AQS的Node放入等待队列中,当计数器为0时将等待队列中的Node拿出来执行。

与CountDownLatch的区别:

  1. CountDownLatch是一个线程等其他线程,CyclicBarrier是多个线程相互等待
  2. CyclicBarrier的计数器能重复使用,调用多次

使用场景: 有四个游戏玩家玩游戏,游戏有三个关卡,每个关卡必须要所有玩家都到达后才能允许通过。其实这个场景里的玩家中如果有玩家A先到了关卡1,他必须等到其他所有玩家都到达关卡1时才能通过,也就是说线程之间需要相互等待。

编程题

交替打印奇偶数

public class PrintOddAndEvenShu {
    private int value = 0;

    private synchronized void printOdd() {
        while (value <= 100) {
            if (value % 2 == 1) {
                System.out.println(Thread.currentThread() + ": -" + value++);
                this.notify();
            } else {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }

    private synchronized void printEven() {
        while (value <= 100) {
            if (value % 2 == 0) {
                System.out.println(Thread.currentThread() + ": --" + value++);
                this.notify();
            } else {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PrintOddAndEvenShu print = new PrintOddAndEvenShu();
        Thread t1 = new Thread(print::printOdd);
        Thread t2 = new Thread(print::printEven);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

 

发布了142 篇原创文章 · 获赞 31 · 访问量 2万+

おすすめ

転載: blog.csdn.net/qq_38905818/article/details/103803411