Javaソースコードの分析とインタビューの質問-ソースコード内のインタビューの質問をキューに入れる

関連するブログ、ムークラス参照列この一連のJavaソースコードとシステムメーカーは簡潔Zhentiインタビュアー
この列の下には、GitHubのアドレスです:
ソースは解決:https://github.com/luanqiu/java8
記事デモ:HTTPS:// GitHubの。 com / luanqiu / java8_demo
クラスメートは必要に応じてそれを見ることができます)

Javaソースコードの分析とインタビューの質問-ソースコード内のインタビューの質問をキューに入れる

入門フレーズ
キューは、ソースコードの面で問題に直面し、インタビュアーから一般入場はゆっくりと、知識の問題として、スレッドプールなどをロックし、キューに尋ねます、ロックので、スレッドプールは、私たちが学んでいないので、ストレートこの章のテーマに行ってきましたキューから始めて、キュー内にあるインタビューの質問を見てみましょう(キューには多くのタイプがあります。この記事では、キューの一般的な特性について話すとき、ほとんどのキューの一般的な特性について話しています。手順)。

1インタビューの質問

1.1キューについての理解、キューとコレクションの違いについて話してください。
回答:キューの理解:

  1. まず、キュー自体はコンテナであり、最下層にもさまざまなデータ構造があります。たとえば、LinkedBlockingQueueは最下部のリンクリスト構造であるため、先入れ先出しの順序を維持できます。たとえば、DelayQueueの最下層は、キューまたはスタックにすることができるため、先入れ先出し、または先入れ先出しの順序など、基礎となるデータ構造が異なるため、操作の実装も異なります。
  2. 一部のキュー(LinkedBlockingQueueなど)は一時的なストレージ機能を提供し、データをキューに入れたり、キューからデータを取得したりできます。両方を同時に行うことができます。
  3. キューは、データを生成するパーティからデータを消費するパーティを切り離します。プロデューサはプロダクションのみを制御し、コンシューマは消費のみを行います。2つの間に必要な接続はありません。キューは、LinkedBlockingQueueなどのプロデューサとコンシューマ間のデータチャネルのようなものです;
  4. また、キューはコンシューマとプロデューサを管理することもできます。たとえば、キュ​​ーがいっぱいで一部のプロデューサがまだデータを配信している場合、キューはプロデューサをブロックして配信されないようにすることができます。人がデータを取得するようになると、キューによってコンシューマが待機し、データがある場合はコンシューマをウェイクアップして、ArrayBlockingQueueなどのデータをコンシューマに返すことができます。
  5. キューにはブロッキング機能もあります。たとえば、キュ​​ーからデータを取得したが、キューにデータがない場合、スレッドは、キューにデータが返されるまでブロックします。

キューとコレクションの違い:

  1. コレクションと同様に、キュー(一部の例外)とコレクションはデータストレージ機能を提供します。基になるストレージデータ構造はやや似ています。たとえば、LinkedBlockingQueueとLinkedHashMapはどちらもリンクリストを使用し、ArrayBlockingQueueとArrayListは両方を使用します。配列です。
  2. コレクションとの違い:
    • 一部のキューと一部のコレクションの基本的なストレージ構造は非常によく似ていますが、異なる目的を達成するために、2つのAPIとそれらの基本的な操作によって提供されるAPIは異なります。

    • キューは、コンシューマとプロデューサの簡単な管理を可能にするブロッキング機能を提供します。キューが空になると、コンシューマをブロックします。他のスレッドが書き込み操作を実行した後、ブロックされたコンシューマは、コンシューマがデータを消費できるように起こされます。 、キューがいっぱいのときも。

    • キューは、プロデューサーとコンシューマーを切り離しており、プロデューサーとコンシューマー間のパイプラインのようなものです。

1.2どのキューにブロック機能があり、どのようにブロックされますか?
回答:キューには、主に次の2つのブロック機能があります。

  1. LinkedBlockingQueueとArrayBlockingQueueは2種類のブロッキングキューです。前者の容量はIntegerの最大値であり、後者の配列のサイズは固定されています。両方のブロッキングキューは容量を指定できます。キューがいっぱいになると、スレッド書き込みデータがある場合、スレッドはブロック、他のスレッドがデータを消費するまで、ブロックされたスレッドはウェイクアップして書き込みを続行します。キューが空の場合、データを取得するスレッドがある場合、スレッドはキューが空でなくなるまでブロックされ、取得を続行します。
  2. SynchronousQueue同期キューは、スレッドが置かれると、対応するスレッドがデータを消費する必要があります。書き込みスレッドは、スレッドが取ると、対応するスレッドがデータを置く必要があります。キューにデータA1を書き込みます。現時点では、コンシューマはありません。スレッドAは戻ることができず、ブロックされます。スレッドAは、スレッドがデータA1を消費するまで戻ることができません。

1.3基になるレイヤーはどのようにブロックしますか?
回答:キュー自体はブロッキング関数を実装していませんが、Conditionの待機とスリープ解除のメカニズムを使用しています。ブロッキングの基本的な実装は、ロックセクションで説明するように、スレッドの状態をスリープに変更することです。

1.4 LinkedBlockingQueueとArrayBlockingQueueの違いは何ですか?
回答:同じ点:
2つのブロッキングメカニズムはほぼ同じで、たとえば、キュ​​ーがいっぱいで空の場合、スレッドはブロックされます。

違い:

  1. LinkedBlockingQueueの最下層はリンクリスト構造であり、容量はデフォルトでIntergeの最大値です。ArrayBlockingQueueの最下層は配列であり、容量は初期化中に指定する必要があります。
  2. 2つの基本的な構造は異なるため、take、put、およびremoveの基本的な実装も異なります。

1.5データをキューに入れても安全ですか?なんで?
A:スレッドセーフです。書き込みの前に、キューは自動的にロックされます。書き込みが完了すると、ロックが自動的に解放され、同時に1つのスレッドのみがキューデータを操作できるようになります。LinkedBlockingQueueを例にとります。 putロックを追加し、チームのテールでのみ操作します。テイク時にはテイクロックを追加し、チームのヘッドのみで操作します。削除すると、プットロックとテイクロックの両方が追加されるため、さまざまな操作がスレッドセーフになります。 、安心してご使用いただけます。

1.6服用するとロックされますか?putとtakeの両方がロックされているため、同時に実行できるメソッドは1つだけです。
答え

  1. はい、それは取得時にもロックされます。たとえば、LinkedBlockingQueueがtakeメソッドを実行すると、データの取得中に現在のデータが削除され、リンクリストのデータ構造が変更されるため、スレッドの安全性を確保するためにロックする必要があります。
  2. これは状況によって異なります。LinkedBlockingQueueの場合、キューの書き込みと取得はロックされますが、2つのロックは異なるため、2つは互いに影響せず、同時に実行できます。ArrayBlockingQueueの場合、putおよびtakeは同じロックなので、一度に実行できるメソッドは1つだけです。

1.7キューのputおよびtakeメソッドを頻繁に使用することの危険性とその回避方法。
回答:キューがいっぱいになると、putメソッドを使用すると、キューがいっぱいになるまでブロックされます。
キューが空の場合、takeメソッドを使用すると、キューにデータがあるまでブロックされます。

どちらの方法も無限(無期限、タイムアウトなし)のブロッキングメソッドであり、すべてのスレッドをブロックするのは簡単です。フローが大きい場合、マシンには使用可能なスレッドがないため、フローが大きい場合は、offerメソッドとpollメソッドを使用することをお勧めします。 2つではなく、タイムアウトのブロック時間を設定するだけで済みます。2つのメソッドがタイムアウト時間外にデータを取得しない場合、それらはデフォルト値(例としてLinkedBlockingQueue)に戻るため、トラフィックが大量に発生することはありません。スレッドはブロックされます。

これは、生産事故が頻繁に発生する理由の1つでもあります。通常のセルフテストでは、プットアンドテイクメソッドを使用しようとしても見つかりません。ソースコードに慣れていない生徒は、問題があることに気づきません。オンライントラフィックが発生したとき、失敗する可能性が高いため、通常、作業でキューを使用する場合は注意が必要です。

1.8データをキューに入れた後、しばらくしてからキューを実行させる方法はありますか?
回答:はい、DelayQueueはこのメカニズムを提供します。このメカニズムは、一定期間後に実行するように設定できます。このキューの唯一の欠点は、データがメモリに保存されることです。再起動して電源を切ると、データが失われやすく、スケジュールされます。通常、数秒以内に長時間を設定することはありません。スケジュールされた時刻を長時間設定する必要がある場合は、延迟队列中间件(この種類のミドルウェアは電源障害を恐れずにデータを保持する)の採用を検討できます

1.9 DelayQueueには要素に対する要件がありますか?文字列をキューに入れることはできますか?
回答:DelayQueueでは、要素がDelayedインターフェースを実装する必要があり、Delayed自体がComparableインターフェースを実装します。Delayedインターフェースの役割は、タイムアウトする時間を定義し、ユーザーのタイムアウト期間をカスタマイズすることです。Comparableインターフェースは主に要素間のインターフェースに使用されますタイムアウト時間の並べ替え、2つを組み合わせることで、前に要素が早く期限切れになる可能性があります。

したがって、StringをDelayQueueに入れることは受け入れられず、コンパイルは成功しません。DelayQueueクラスが定義されると、それはジェネリック型によって定義されます。ジェネリック型は、Delayedインターフェースのサブクラスである必要があります。

1.10 DelayQueueはどのようにして期限切れの要素を最初に実行させますか?
回答:DelayQueueの要素は両方とも、DelayedインターフェースとComparableインターフェースを実装しており、SortableのCompareToメソッドを使用してソートします。この関数を使用して、compareToメソッドで有効期限と現在の時刻の差を実装できるため、期限切れの要素が早くなります、計算された差が小さいほど、早く実行されます。

1.11 SynchronousQueueのサイズを確認する方法
回答:この質問は罠です。この質問は、まずSynchronousQueueを設定してサイズを確認します。実際、SynchronousQueue自体には容量がないため、容量のサイズを確認できません。内部のサイズメソッドは、死に戻るためのものです。 0。

1.12 SynchronousQueueの下部にはいくつかのデータ構造がありますが、2つの違いは何ですか?
回答:最下層のデータ構造には、キューとスタックの2種類があります。

2つの違い:
キューは先入れ先出しの順序を維持するため、デキューされる最も高度な要素が最初に消費されます。これはフェアと呼ばれ、スタックは先入れ先出しの順序であり、スタックに最初に入るデータです。最終的に消費される可能性があり、これを不公正と呼びます。
2つはデータ構造が異なるため、takeメソッドとputメソッドが異なります詳細については、「SynchronousQueueのソースコード分析」の章を参照してください。

1.13 SynchronousQueueの下部でスタックが使用されていると仮定すると、スレッド1はテイク操作によってブロックされ、スレッド2は書き込み操作を実行します。
回答:これはよい質問です。また、SynchronousQueueを理解する上での中心的な問題でもあります。

最初に、スレッド1がブロックされます。このとき、スタックヘッドはスレッド1です。このとき、スレッド2は書き込み操作を実行し、書き込みデータがスタックヘッドの一致属性に割り当てられ、スレッド1がウェイクアップします。スレッド1がウェイクアップした後、スタックヘッダーのmatch属性を使用すると、書き込みデータを取得できます。

厳密に言うと、putオペレーションがデータを直接テイクに転送するのではなく、putオペレーションがスタックヘッダーのデータを変更するため、テイクはスタックヘッダーから直接データを取得でき、スタックヘッダーはテイクとputオペレーションの間の通信媒体です。 。

1.14固定サイズのキューを使用する場合、いくつかのタイプのキューから選択できますが、違いは何ですか?
回答:LinkedBlockingQueueおよびArrayBlockingQueueを使用できます。

前者はリンクリスト、後者は配列です。リンクリストを追加する場合、新しいデータと末尾データの関連付けが確立されている限り、配列を追加するときにインデックスの位置を考慮する必要があります(takeIndexとputIndexは別々に記録されます)データのインデックスを取得し、データのインデックスを挿入します)、配列の最後の位置まで増加すると、次回から再び追加され始めます。

1.15 ArrayBlockingQueueは動的に拡張できますか?配列の最後の位置が使用されたときに何をすべきか?
回答:いいえ、ArrayBlockingQueueの最下層は配列ですが、動的に拡張することはできません。

put操作が配列の最後の位置を使用すると想定すると、次のputは配列0の位置から再開する必要があります。

テイク操作が配列の最後の位置を使用すると仮定すると、次のテイクは配列0の位置から再び開始されます。

1.16 ArrayBlockingQueueはどのようにしてインデックス位置を見つけますか?ハッシュアルゴリズムを使用して計算されますか?
回答:ArrayBlockingQueueにはtakeIndexとputIndexの2つの属性があり、それぞれ次のテイクとプットの位置を識別します。テイクとプットが完了するたびに、1つずつ増加します。最下部のレイヤーは配列ですが、HashMapとは異なり、渡されません。ハッシュアルゴリズムによって計算されます。

2まとめ

キューは、ロックやスレッドプールなどの複雑なAPIの基礎です。多くのインタビュアーは、これらのAPIを要求するときにキューについての知識を求めます。よく答えない場合、インタビュアーはロックとスレッドプールしか使用していないと思うかもしれません。ただし、基本的な原理と実装は完全には理解されていないため、キューは依然として非常に重要ですが、キューのソースコードはより複雑です。ソースコードを理解するには、デバッグメソッドを試すことをお勧めします。

公開された40元の記事 ウォンの賞賛1 ビュー4982

おすすめ

転載: blog.csdn.net/aha_jasper/article/details/105525836
おすすめ