インタビューの質問の要約(3)マルチスレッド

35.並列と並行の違いは何ですか?

 

  • 並列とは、2つ以上のイベントが同時に発生することを意味し、同時実行とは、2つ以上のイベントが同じ時間間隔で発生することを意味します。

  • 並列処理は、異なるエンティティ上の複数のイベントであり、同時実行性は、同じエンティティ上の複数のイベントです。

  • 複数のタスクは1つのプロセッサーで「同時に」処理され、複数のタスクは複数のプロセッサーで同時に処理されます。hadoop分散クラスターなど。

 

したがって、並行プログラミングの目標は、プロセッサーの各コアを最大限に活用して最高の処理パフォーマンスを達成することです。

 

36.スレッドとプロセスの違いは?

 

つまり、プロセスはプログラムの操作とリソース割り当ての基本単位であり、プログラムには少なくとも1つのプロセスがあり、プロセスには少なくとも1つのスレッドがあります。プロセスは実行中に独立したメモリユニットを持ち、複数のスレッドがメモリリソースを共有して、切り替えの回数を減らします。スレッドは、プロセスのエンティティ、CPUスケジューリングとディスパッチの基本単位、およびプログラムとは独立して実行できる基本単位です。同じプロセス内の複数のスレッドを同時に実行できます。

 

37.デーモンスレッドとは何ですか?

 

デーモンスレッド(つまり、デーモンスレッド)はサービススレッドであり、正確には他のスレッドにサービスを提供します。

 

38.スレッドを作成する別の方法は何ですか?

 

①。スレッドクラスを継承してスレッドクラスを作成する

 

  • Threadクラスのサブクラスを定義し、このクラスのrunメソッドを書き換えます。runメソッドのメソッド本体は、スレッドによって実行されるタスクを表します。したがって、run()メソッドは実行体と呼ばれます。

  • Threadサブクラスのインスタンスを作成します。つまり、スレッドオブジェクトを作成します。

  • スレッドオブジェクトのstart()メソッドを呼び出して、スレッドを開始します。

 

②。Runnableインターフェイスを介してスレッドクラスを作成する

 

  • runnableインターフェースの実装クラスを定義し、インターフェースのrun()メソッドを書き直しますrun()メソッドのメソッド本体は、スレッドのスレッド実行本体でもあります。

  • Runnable実装クラスのインスタンスを作成し、このインスタンスをThreadターゲットとして使用して、実際のスレッドオブジェクトであるThreadオブジェクトを作成します。

  • スレッドオブジェクトのstart()メソッドを呼び出して、スレッドを開始します。

 

③。CallableとFutureでスレッドを作成する

 

  • Callableインターフェースの実装クラスを作成し、call()メソッドを実装します。call()メソッドはスレッド実行本体として機能し、戻り値を持ちます。

  • Callable実装クラスのインスタンスを作成し、FutureTaskクラスを使用してCallableオブジェクトをラップします。FutureTaskオブジェクトは、Callableオブジェクトのcall()メソッドの戻り値をカプセル化します。

  • ThreadオブジェクトのターゲットとしてFutureTaskオブジェクトを使用して、新しいスレッドを作成および開始します。

  • 子スレッドの実行後に戻り値を取得するには、FutureTaskオブジェクトのget()メソッドを呼び出します。

 

39.実行可能と呼び出し可能の違いは何ですか?

 

少し深い質問ですが、Javaプログラマーが幅広い知識を学習していることも確認してください。

 

  • Runnableインターフェースのrun()メソッドの戻り値はvoidであり、run()メソッドでコードを実行するだけです。

  • Callableインターフェースのcall()メソッドは戻り値を持ち、ジェネリック型です。FutureおよびFutureTaskと共に使用して、非同期実行の結果を取得できます。

 

40.スレッドの状態はどうですか?

 

スレッドには通常、作成済み、準備完了、実行中、ブロック済み、および停止の5つの状態があります。

 

  • 状態を作成します。スレッドオブジェクトが生成されるとき、オブジェクトのstartメソッドは呼び出されません。つまり、スレッドは作成状態にあります。

  • 準備完了状態。スレッドオブジェクトのstartメソッドが呼び出されると、スレッドは準備完了状態になりますが、スレッドスケジューラはこのスレッドを現在のスレッドとして設定しておらず、現時点では準備完了状態です。スレッドの実行後は、待機またはスリープから復帰した後、準備完了状態になります。

  • 実行ステータス。スレッドスケジューラは、準備完了状態のスレッドを現在のスレッドとして設定します。この時点で、スレッドは実行状態になり、run関数でコードの実行を開始します。

  • ブロックされた状態。スレッドが実行中の場合、スレッドは一時停止します。通常、実行を続行する前に、一定の時間(リソースの準備ができているなど)が発生するまで待機します。スリープ、一時停止、待機などのメソッドにより、スレッドがブロックされる可能性があります。

  • 死の状態。スレッドのrunメソッドが終了した場合、またはstopメソッドが呼び出された場合、スレッドは終了します。デッドスレッドの場合、startメソッドを使用して準備することはできません。   

 

41.スリープ()とウェイト()の違いは何ですか?

 

sleep():このメソッドは、スレッドクラス(Thread)の静的メソッドであり、呼び出しスレッドがスリープ状態に入り、他のスレッドに実行機会を与えることができます。スリープ時間が終了すると、スレッドは準備状態に入り、CPU実行時間について他のスレッドと競合します。sleep()は静的メソッドであるため、オブジェクトのマシンロックを変更することはできません。sleep()メソッドが同期ブロックで呼び出されると、スレッドはスリープ状態になりますが、オブジェクトのマシンロックは解放されず、他のスレッドはこれにアクセスできません。オブジェクト。

 

wait():wait()はObjectクラスのメソッドです。スレッドがwaitメソッドを実行すると、スレッドはオブジェクトに関連する待機プールに入り、同時にオブジェクトのマシンロックを解放して、他のスレッドがオブジェクトにアクセスできるようにします。 notify、notifyAllメソッドで待機中のスレッドをウェイクアップ

 

42. notify()とnotifyAll()の違いは何ですか?

 

  • スレッドがオブジェクトのwait()メソッドを呼び出す場合、スレッドはオブジェクトの待機プールにあり、待機プール内のスレッドはオブジェクトのロックを競合しません。

  • スレッドがオブジェクトのnotifyAll()メソッド(すべての待機スレッドを起動する)またはnotify()メソッド(待機スレッドのみをランダムに起動する)を呼び出すと、起動されたスレッドはオブジェクトのロックプールに入ります。スレッドはオブジェクトロックを求めて競合します。つまり、notifyを呼び出した後、スレッドが待機プールからロックプールに入る限り、notifyAllはオブジェクト待機プール内のすべてのスレッドをロックプールに移動し、ロックの競合を待ちます。

  • 優先度の高いスレッドは、オブジェクトロックについて競合する可能性が高くなります。スレッドがオブジェクトロックについて競合しない場合、そのスレッドはロックプールに残ります。スレッドが再度wait()メソッドを呼び出した場合にのみ、待機中のプールに戻ります。で。オブジェクトロックを競合するスレッドは、同期コードブロックが実行されるまで実行を続け、オブジェクトロックを解放します。その後、ロックプール内のスレッドがオブジェクトロックを競合し続けます。

 

43.スレッドのrun()とstart()の違いは何ですか?

 

各スレッドは、スレッドボディと呼ばれる特定のThreadオブジェクトrun()に対応するメソッドを介して操作を完了します。Threadクラスのstart()メソッドを呼び出してスレッドを開始します。

 

start()メソッドはスレッドを開始します。これは、マルチスレッドを本当に実装しています。この時点では、runメソッドの本体コードの実行が完了するのを待つ必要はありません。次のコードの実行を直接続行できますが、今回はスレッドが準備完了状態で実行されていません。次に、このThreadクラスを介してメソッドrun()を呼び出し、実行状態を完了します。メソッドrun()は、実行されるスレッドの内容を含むスレッド本体と呼ばれます。Runメソッドは終了し、スレッドは終了します。次に、CPUは他のスレッドをスケジュールします。

 

run()メソッドはこのスレッドにあり、スレッド内の関数であり、マルチスレッドではありません。run()を直接呼び出す場合、実際には通常の関数を呼び出すことと同じです。ダイレクトスタンバイrun()メソッドは、run()メソッドが完了するまで待機してから次のコードを実行する必要があるため、実行パスは1つしかなく、スレッドはありません。機能なので、マルチスレッド実行ではrun()メソッドの代わりにstart()メソッドを使用します。

 

44.スレッドプールを作成する方法は何ですか?

 

①。newFixedThreadPool(int nThreads)

 

固定長スレッドプールを作成し、タスクが送信されるたびにスレッドを作成します。スレッドプールの最大数に達すると、スレッドサイズは変更されなくなり、スレッドが予期しないエラーで終了すると、スレッドプールが補足します。新しいスレッド。

 

②。newCachedThreadPool()

 

キャッシュ可能なスレッドプールを作成します。スレッドプールのサイズが処理要件を超えると、アイドルスレッドが自動的に回復されます。需要が増加すると、新しいスレッドを自動的に追加できます。スレッドプールのサイズに制限はありません。

 

③。newSingleThreadExecutor()

 

これは、タスクを実行する単一のワーカースレッドを作成するシングルスレッドのエグゼキューターです。このスレッドが異常終了した場合、新しいスレッドが作成されてスレッドが置き換えられます。その機能は、キュー内のタスクの順序に従ってタスクが確実に順番に実行されるようにすることです。

 

④。newScheduledThreadPool(int corePoolSize)

 

固定長のスレッドプールを作成し、タイマーと同様に遅延または時間指定された方法でタスクを実行します。

 

45.スレッドプールの状態は何ですか?

 

スレッドプールには5つの状態があります。実行中、シャットダウン、停止、片付け、終了です。

スレッドプールの状態切り替えフレームワークの図:

 

46.スレッドプールのsubmit()メソッドとexecute()メソッドの違いは何ですか?

 

  • 受け取ったパラメータが異なります

  • submitには戻り値がありますが、executeにはありません

  • 例外処理を容易にするために送信する

 

47. Javaプログラムでマルチスレッド操作の安全性を確保する方法は?

 

スレッドセーフティは3つの側面に反映されます。

 

  • 原子性:相互に排他的なアクセスを提供し、1つのスレッドのみが同時にデータを操作できます(原子、同期)。

  • 可視性:1つのスレッドによるメインメモリの変更は、他のスレッドから(同期、揮発性)いつでも確認できます。

  • 順序付け:スレッドは他のスレッドでの命令の実行順序を監視しますが、命令の順序変更により、監視結果は一般に乱れます(前の原則)。

 

48.マルチスレッドロックアップグレードの原則は何ですか?

 

Javaでは、低レベルから高レベルの4つのロック状態があり、ステートレスロック、バイアスロック、軽量ロック、および重量ロックであり、これらの状態は競争に伴って徐々にアップグレードされます。ロックはアップグレードできますが、ダウングレードできません。

 

ロックのアップグレードのグラフィカルプロセス: 

 

 

49.デッドロックとは何ですか?

 

デッドロックとは、競合するリソースや相互の通信による2つ以上のプロセスによって引き起こされるブロッキング現象を指します。外部からの力がないと、プロセスは続行できません。このとき、システムがデッドロック状態にある、またはシステムにデッドロックが発生しているといわれ、常に待ち合わせているこれらのプロセスをデッドロックプロセスと呼びます。これは、オペレーティングシステムレベルでのエラーであり、プロセスデッドロックの略です。1965年にバンカーアルゴリズムを研究したときに、ダイクストラによって最初に提案されました。これは、コンピューターオペレーティングシステムおよびコンカレントプログラミング分野全体で最も困難な問題の1つです。

 

50.デッドロックを防ぐには?

 

デッドロックに必要な4つの条件:

 

  • 相互に排他的な状態:プロセスは他のプロセスが割り当てられたリソースにアクセスすることを許可しません。他のプロセスがリソースにアクセスする場合、それらはリソースを所有するプロセスがリソースを解放するまでしか待機できません

  • リクエストアンドホールドの条件:プロセスは特定のリソースを取得した後、別のリソースをリクエストしますが、そのリソースは他のプロセスによって占有されている可能性があります。リクエストはブロックされますが、それ自体が取得したリソースは保持されます。

  • 不可侵の状態:プロセスが取得したリソースを指します。使用が完了するまでは、奪うことはできず、使用後にのみ解放できます。

  • ループ待機状態:デッドロックが発生した後、いくつかのプロセス間でループとエンドの関係を形成するプロセスを指します

 

デッドロックにはこれらの4つの条件が必要ですが、システムにデッドロックがある限り、これらの条件が成立している必要があり、上記の条件のいずれかが満たされない限り、デッドロックは発生しません。

 

デッドロックの原因、特にデッドロックに必要な4つの条件を理解すると、デッドロックを可能な限り回避、防止、および解放できます。

 

したがって、システム設計とプロセススケジューリングの側面では、これらの4つの必要な条件が確立されないようにする方法、合理的なリソース割り当てアルゴリズムを決定する方法、およびプロセスがシステムリソースを永続的に占有しないようにする方法に注意してください。

 

また、待機中のプロセスがリソースを占有しないようにする必要もあります。したがって、リソースの割り当てについては、合理的な計画を立てる必要があります。


51. ThreadLocalとは何ですか?使用シナリオは何ですか?

 

スレッドローカル変数は内部スレッドに限定された変数であり、スレッド自体に属し、複数のスレッド間で共有されません。Javaは、スレッドローカル変数をサポートするThreadLocalクラスを提供します。これは、スレッドの安全性を実現する方法です。ただし、管理環境(Webサーバーなど)でスレッドローカル変数を使用する場合は注意してください。この場合、ワーカースレッドのライフサイクルは、アプリケーション変数のライフサイクルよりも長くなります。作業が完了してもスレッドローカル変数が解放されないと、Javaアプリケーションでメモリリークが発生する可能性があります。

 

52.同期の基本的な実装原理について教えてください。

 

Synchronizedは、メソッドまたはコードブロックの実行時に一度に1つのメソッドのみがクリティカルセクションに入ることができるようにし、共有変数のメモリの可視性を保証することもできます。

 

Javaのすべてのオブジェクトはロックとして使用でき、これが同期同期の基本です。

 

  • 一般的な同期方法。ロックは現在のインスタンスオブジェクトです

  • 静的同期メソッド。ロックは現在のクラスのクラスオブジェクトです。

  • 同期メソッドブロック、ロックは括弧内のオブジェクトです

53.同期型と揮発性の違いは何ですか?

 

  • volatileの本質は、レジスター(作業メモリー)の現在の変数の値が不明確であり、メインメモリーから読み取る必要があることをjvmに伝えることです;同期は現在の変数をロックすることであり、現在のスレッドのみが変数にアクセスでき、他のスレッドはブロックされます。

  • 揮発性は変数レベルでのみ使用でき、同期は変数、メソッド、およびクラスレベルで使用できます。

  • 揮発性は変数の変更された可視性のみを達成でき、原子性は保証できませんが、同期は変数の変更された可視性と原子性を保証できます。

  • volatileはスレッドのブロッキングを引き起こしません;同期するとスレッドのブロッキングが生じる可能性があります。

  • volatileとマークされた変数は、コンパイラーによって最適化されません。synchronizedとマークされた変数は、コンパイラーによって最適化される場合があります。

 

54.同期とロックの違いは何ですか?

 

  • まず、synchronizedはjavaに組み込まれたキーワードであり、jvmレベルではLockはjavaクラスです。

  • Synchronizedはロックステータスを取得するかどうかを判断できません。Lockはロックを取得するかどうかを判断できます。

  • synchronizedは自動的にロックを解放します(スレッドは同期コードの実行後にロックを解放します。bスレッドの実行プロセス中に例外が解放されます)、lockは手動でロックを解放する必要があります(unlock()メソッドでロックを解放します)。それ以外の場合、スレッドが簡単に終了する原因になります。ロックする

  • 同期キーワードを使用する2つのスレッド1および2。現在のスレッド1がロックを取得した場合、スレッド2スレッドは待機します。スレッド1がブロックされている場合、スレッド2は永久に待機し、ロックは必ずしも待機しません。ロックを取得できない場合、スレッドは待機せずに終了できます。

  • 同期されたロックは、再入可能で、割り込み不可能で、不公平である可能性がありますが、ロックロックは、再入可能で、決定可能で、公平なものである可能性があります(両方)

  • ロックロックは、多数の同期コードの同期問題に適しています。同期ロックは、少数のコードの同期問題に適しています。

 

55.同期とReentrantLockの違いは何ですか?

 

Synchronizedは、reentrantLockがクラスであるかのように同じキーワードですが、ReentrantLockは2つの本質的な違いです。ReentrantLockはクラスであるため、同期よりも柔軟な機能を提供します。継承可能で、メソッドを持つことができ、さまざまなクラス変数を持つことができます。同期よりもReentrantLockのスケーラビリティは、いくつかの点で反映されます。 

 

  • ReentrantLockは、デッドロックを回避するために、ロックを取得するための待機時間を設定できます。 

  • ReentrantLockはさまざまなロック情報を取得できます

  • ReentrantLockはマルチチャネル通知を柔軟に実現できます 

 

さらに、2つのロックメカニズムは実際には異なります。ReentrantLockの最下部はUnsafeのパークメソッドを呼び出してロックし、同期された操作はオブジェクトヘッダーのマークワードである必要があります。

56.原子の原理について教えてください。

 

Atomicパッケージのクラスの基本的な特性は、マルチスレッド環境で、複数のスレッドが単一の(基本タイプと参照タイプを含む)変数を同時に操作する場合、それは排他的です。つまり、複数のスレッドが同時に変数を評価する場合です。更新時には、1つのスレッドのみが成功し、失敗したスレッドはスピンロックのように試行を続け、実行が成功するまで待機できます。

 

Atomicシリーズのクラスのコアメソッドは、安全でないクラスのいくつかのローカルメソッドを呼び出します。Unsafeクラス(フルネームはsun.misc.Unsafe)であることを知っておく必要があります。このクラスには、多くの直接メモリ割り当てやアトミック操作呼び出しなど、Cコードに対する多数の操作が含まれています。安全とは、多数のメソッド呼び出しが潜在的な安全上の危険を伴い、慎重に使用する必要があることを通知することです。それ以外の場合は、重大な結果を引き起こします。たとえば、unsafeを介してメモリを割り当てる場合、特定の領域を自分で指定すると、C ++のようなポインターが他のプロセスの範囲外です。

 

リリース9件のオリジナルの記事 ウォンの賞賛0 ビュー246

おすすめ

転載: blog.csdn.net/Fabri/article/details/105491882