JavaRush /Java Blog /Random-JA /翻訳: スレッドごとのインタビューの質問トップ 50。パート2。
KapChook
レベル 19
Volga

翻訳: スレッドごとのインタビューの質問トップ 50。パート2。

Random-JA グループに公開済み
オリジナル記事Top 50 Java Thread Interviewquestions Answers for Freshers, Experienced Programmers の 翻訳の後半です。 最初の部分。
  1. スレッドがロックを保持しているかどうかを確認するにはどうすればよいですか?

  2. 電話インタビューでこの質問に出会うまで、スレッドが現在ロックを保持しているかどうかを確認できるとは知りませんでした。java.lang.Thread にはholdsLock() メソッドがあり、現在のスレッドが特定のオブジェクトのモニターを保持している場合にのみ true を返します。
  3. スレッドダンプを取得するにはどうすればよいですか?

  4. スレッド ダンプを使用すると、スレッドが現在何を行っているかを確認できます。スレッド ダンプを取得するには、オペレーティング システムに応じていくつかの方法があります。Windows では ctrl + Break の組み合わせを使用でき、Linux では kill -3 コマンドを使用できます。jstack ユーティリティを使用することもできます。このユーティリティはプロセス ID を操作し、別の jps ユーティリティを使用して確認できます。
  5. スレッドのスタック サイズを制御するためにどの JVM パラメータが使用されますか?

  6. これは、Java でスレッドのスタックのサイズを制御するために使用される単純な -Xss パラメータの 1 つです。
  7. 同期ロックとリエントラントロックの違いは?

  8. 相互排他を実現する唯一の方法が synchronized キーワードを使用することだったことがありますが、メソッドやコード ブロックを超えてロックを拡張できないなど、いくつかの欠点があります。Java 5 では、Lock インターフェースを通じてより詳細な制御を提供することで、この問題を解決しています。ReentrantLock は、暗黙的なモニターと同じ基本的な動作とセマンティクスをロックに提供する共通のロック実装であり、同期メソッドを使用して実現されますが、機能が強化されています。
  9. 3 つのスレッド T1、T2、および T3 があるとしますか? シーケンス T1、T2、T3 を実装するにはどうすればよいですか?

  10. 一貫性はさまざまな方法で実現できますが、単に join() メソッドを使用して、別のスレッドの実行が終了したときにスレッドを開始することもできます。指定されたシーケンスを実装するには、最初に最後のスレッドを開始し、次に join() メソッドを逆の順序で呼び出す必要があります。つまり、T3 が T2.join を呼び出し、T2 が T1.join を呼び出すため、T1 が最初に終了し、T3 が最後に終了します。 。
  11. イールドメソッドは何をするのですか?

  12. yield メソッドは、別のスレッドが実行できるようにスレッドに CPU を放棄するように要求する 1 つの方法です。これは静的メソッドであり、現在のスレッドがプロセッサを放棄することを保証するだけであり、どのスレッドで実行するかは決定しません。
  13. ConcurrentHashMap の同時実行レベルは何ですか?

  14. ConcurrentHashMap は、実際のマップをセクションに分割することで、スケーラビリティとスレッドの安全性を実現します。この分離は、並列処理のレベルを使用して実現されます。これは ConcurrentHashMap コンストラクターのオプションのパラメーターであり、デフォルト値は 16 です。
  15. セマフォとは何ですか?

  16. セマフォは新しいタイプのシンクロナイザーです。これはカウンター付きセマフォです。概念的には、セマフォは一連の権限を制御します。各acquire()は、必要に応じて、アクセス許可が利用可能になる前にブロックし、アクセス許可を取得します。各 release() はアクセス許可を追加し、ブロッキングしている取得者を解放する可能性があります。ただし、これは実際の権限オブジェクトを使用しません。セマフォは単に利用可能なセマフォの数を保存し、それに応じて動作します。セマフォは、プールされたデータベースへの接続など、数量が限られている高価なリソースを保護するために使用されます。
  17. スレッド プール キューがすでにいっぱいでタスクを送信するとどうなりますか?

  18. スレッド プールのキューがいっぱいの場合、送信されたタスクは「拒否」されます。ThreadPoolExecutor の submit() メソッドは RejectedExecutionException をスローし、その後 RejectedExecutionHandler が呼び出されます。
  19. スレッドプールの submit() メソッドとexecute() メソッドの違いは何ですか?

  20. どちらの方法もタスクをスレッド プールに送信する方法ですが、両者には若干の違いがあります。Execute(Runnable command) は Executor インターフェイスで定義され、将来的に指定されたタスクを実行しますが、さらに重要なことに、何も返しません。一方、submit() はオーバーロードされたメソッドであり、Runnable および Callable タスクを受け入れることができ、実行のキャンセルや計算の結果の待機に使用できる Future オブジェクトを返すことができます。このメソッドは、Executor インターフェイスを継承する ExecutorService インターフェイスで定義され、ThreadPoolExecutor や ScheduledThreadPoolExecutor などの各スレッド プール クラスはこれらのメソッドを継承します。
  21. ブロック方法とは何ですか?

  22. ブロッキング メソッドは、タスクが完了するまでブロックするメソッドです。たとえば、ServerSocket accept() メソッドは、クライアントの接続を待機している間ブロックします。ここで、ブロッキングとは、ジョブが完了するまで制御が呼び出し元のメソッドに戻らないことを意味します。一方、タスクが完了する前に完了する非同期メソッドやノンブロッキング メソッドもあります。
  23. Swing スレッドは安全ですか?

  24. 簡単に言えば、いいえ、Swing はスレッドセーフではありませんが、面接官が質問しなくても、それが何を意味するのか説明する必要があります。Swing がスレッドセーフではないと言うとき、通常は、Swing が複数のスレッドによって変更できないコンポーネントであるという事実を指します。GUI コンポーネントに対するすべての変更は AWT スレッドで行う必要があり、Swing はそのような変更をスケジュールするための同期メソッドと非同期メソッドを提供します。
  25. invokeAndWait と invokeLater の違いは?

  26. これら 2 つの Swing API メソッドにより、開発者はイベント マネージャー スレッドではなくスレッドから GUI コンポーネントを更新できます。InvokeAndWait() は、進行状況バーなどの GUI コンポーネントを同期的に更新します。進行状況が進むたびに、変更を反映するためにバーを更新する必要があります。進行状況が別のスレッドで追跡されている場合は、invokeAndWait() を呼び出して、そのコンポーネントを更新するイベント ディスパッチャー スレッドを割り当てる必要があります。また、invokeLater() はコンポーネントを更新するための非同期呼び出しです。
  27. どの Swing API メソッドがスレッドセーフですか?

  28. この質問も Swing とスレッド セーフに関するものです。Swing コンポーネントはスレッド セーフではありませんが、複数のスレッドから安全に呼び出すことができるメソッドがあります。repaint() と revalidate() がスレッドセーフであることはわかっていますが、さまざまな Swing コンポーネントには、JTextComponent の setText() メソッドや JTextArea の insert() メソッドや append() メソッドなど、他のメソッドもあります。
  29. 不変オブジェクトを作成するにはどうすればよいですか?

  30. この質問はマルチスレッドと同時実行性とは何の関係もないように見えるかもしれませんが、実際には関係あります。不変性は、すでに複雑な並列コードを簡素化するのに役立ちます。不変オブジェクトは同期なしで伝播される可能性があるため、開発者にとって非常に高価です。残念ながら、Java にはオブジェクトを不変にする @Immutable アノテーションがありません。これについては開発者が懸命に取り組む必要があります。不変オブジェクトを作成するには、コンストラクターでの初期化、セッターなし、参照漏洩なし、可変オブジェクトの個別のコピーの保存という基本に従う必要があります。
  31. 読み取り書き込みロックとは何ですか?

  32. 一般に、ReadWriteLock は、並列アプリケーションのパフォーマンスを向上させるためのロック解析手法の結果です。これは Java 5 で追加されたインターフェイスです。これは、関連するロックのペア (読み取り操作用と書き込み操作用) で動作します。リーダーのロックは、ライターがなくなるまで、複数の読み取りスレッドによって同時に保持されることがあります。書き込みロックは排他的です。必要に応じて、ルールセットとのインターフェイスを実装したり、最大 65535 個の再帰書き込みロックと 65535 個の読み取りロックをサポートする ReentrantReadWriteLock を使用したりできます。
  33. ビジースピンとは何ですか?

  34. Busy Spin は、プログラマが特定の条件下でスレッドを強制的に待機させるために使用する手法です。プロセッサの制御を譲渡する従来のメソッド wait()、sleep()、yield() とは異なり、このメソッドはプロセッサを譲渡せず、単に空のループを実行します。なぜこんなことをする人がいるのでしょうか?プロセッサーのキャッシュを保存します。マルチコア システムでは、一時停止されたスレッドが別のコアで実行を継続する可能性があります。これはキャッシュの再構築を意味します。コストのかかる再構築を避けるために、プログラマはビジー スピンを使用して待ち時間を短縮することを好みます。
  35. 揮発性変数とアトミック変数の違いは?

  36. これは非常に興味深い質問です。揮発性変数とアトミック変数は最初は非常によく似ていますが、それでも異なります。Volatile 変数は、後続の書き込みの前に書き込みが発生することを保証しますが、アトミック性は保証しません。たとえば、count++ 操作は、単に count が volatile として宣言されているという理由だけでアトミックになりません。一方、AtomicInteger クラスは、このような複雑な操作をアトミックに実行するためのアトミック メソッドを提供します。たとえば、getAndIncrement() はインクリメント演算子のアトミックな置き換えであり、現在の値をアトミックに 1 つインクリメントするために使用できます。他のデータ型のアトミック バージョンもあります。
  37. スレッドが同期ブロックで例外をスローした場合はどうなりますか?

  38. これも、通常の Java プログラマーにとってはひっかけ問題です。同期ブロックを終了する方法に関係なく、通常は実行を終了するか、突然例外をスローするかにかかわらず、スレッドは同期ブロックに入ったときに取得したロックを解放します。これが、ロックを解放するときに特別な注意が必要なインターフェイスよりも、同期ロック ブロックを好む理由の 1 つです。通常は、finally ブロックでロックを解放します。
  39. Singleton の二重チェック ロックとは何ですか?

  40. これは面接で最も人気のある質問の 1 つですが、その人気にもかかわらず、候補者が答える可能性はせいぜい 50% です。半分はコードの作成で失敗し、残りの半分はコードが Java 1.5 でどのように壊れて修正されたかを説明するときに失敗します。これはスレッドセーフなシングルトンを作成する古い方法で、シングルトン インスタンスが最初にインスタンス化されるときにのみブロックすることでパフォーマンスの最適化を試みますが、複雑さと JDK 1.4 で壊れていたという事実のため、個人的には好きではありません。それ。ただし、このアプローチを好まない場合でも、面接の観点からこのアプローチを知っておくことは役に立ちます。
  41. スレッドセーフなシングルトンを作成するにはどうすればよいですか?

  42. この質問は前の質問を補完するものです。二重チェックされたロックが好きではないと言うと、面接官はスレッドセーフなシングルトンを作成する別の方法について尋ねざるを得なくなります。そして、クラスの読み込み機能と静的変数の初期化機能を利用して Singleton をインスタンス化することも、強力な列挙型を利用することもできます。
  43. 並列プログラミングで従う習慣を 3 つ挙げてください。

  44. これは私のお気に入りの質問です。並列コードを作成する際には、パフォーマンス、デバッグ、サポートに役立つ特定のルールに従う必要があると考えているからです。以下は、すべての Java プログラマーが従うべきだと私が考える 3 つの最良のルールです。
    • スレッドには常に意味のある名前を付けてください
    • 並列コードでバグを見つけたり例外を追跡したりするのは、かなり難しい作業です。OrderProcessor、QuoteProcessor、または TradeProcessor は Thread-1 よりもはるかに優れています。スレッド 2 とスレッド 3。名前は、スレッドによって実行されるタスクを反映する必要があります。すべての主要なフレームワーク、さらには JDK もこのルールに従います。
    • ブロックを避けるか同期範囲を減らす
    • ブロッキングにはコストがかかりますが、コンテキストの切り替えにはさらにコストがかかります。同期とブロックをできる限り回避し、クリティカルセクションを必要最小限に減らします。これが、私が時間指定方式よりも時間指定ブロックを好む理由です。ブロックの範囲を完全に制御できるからです。
    • シンクロナイザーと待機して通知の間で、シンクロナイザーを選択します
    • まず、CountDownLatch、Semaphore、CyclicBarrier、Exchanger などのシンクロナイザーによりコーディングが簡素化されます。待機と通知を使用した複雑な制御フローを実装するのは非常に困難です。第 2 に、これらのクラスは業界の最高の人材によって作成および保守されており、将来の JDK リリースで最適化されるか、より良いコードに置き換えられる可能性が高くなります。高レベルの同期ユーティリティを使用すると、これらすべての利点が自動的に得られます。
    • 同時収集と同期収集の間で、同時収集を選択します
    • これも簡単に従うことができ、メリットを享受できるシンプルなルールです。同時コレクションは同期コレクションよりも拡張性が高いため、並列コードを作成する場合は同時コレクションを使用することをお勧めします。したがって、次回マップが必要になったときは、Hashtable について考える前に ConcurrentHashMap について考えてください。
  45. スレッドを強制的に開始するにはどうすればよいですか?

  46. これは、ガベージ コレクションを強制的に実行する方法に関する質問です。つまり、もちろん System.gc() を使用してクエリを作成することはできますが、何も保証されません。Java ではスレッドを強制的に開始する方法はまったくありません。これはスレッド スケジューラによって制御され、Java はスレッドを制御するための API を提供しません。Java のこの部分は依然としてランダムです。
  47. フォーク/結合フレームワークとは何ですか?

  48. JDK 7 で導入された Fork/Join フレームワークは、開発者が最新のサーバーの複数のプロセッサを活用できるようにする強力なユーティリティです。これは、再帰的に小さな粒子に分割できる作業向けに設計されています。目標は、利用可能なすべてのコンピューティング能力を使用してアプリケーションのパフォーマンスを向上させることです。このフレームワークの大きな利点の 1 つは、ワークスチール アルゴリズム (作業 - 作業とスチール - スチール) を使用していることです。ジョブがなくなったワーカー スレッドは、まだビジー状態の他のスレッドからジョブを盗む可能性があります。
  49. wait() と sleep() の呼び出しの違いは何ですか?

  50. 待機とスリープは両方とも Java アプリケーションにおける一種の一時停止を表しますが、これらはさまざまなニーズに対応するデバイスです。待機は内部スレッド通信に使用され、待機条件が true の場合はロックを放棄し、別のスレッドのアクションにより待機条件が false になった場合は通知を待機します。一方、sleep() メソッドは、単にプロセッサを放棄するか、現在のスレッドの実行を指定された時間停止します。sleep() を呼び出しても、現在のスレッドが保持しているロックは解放されません。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION