Java マルチスレッドに関する面接の質問

(*-*)浩
リリース: 2019-12-11 15:05:35
オリジナル
2900 人が閲覧しました

Java マルチスレッドに関する面接の質問

スレッドとは何ですか?

スレッドは、オペレーティング システムが操作のスケジューリングを実行できる最小単位であり、プロセスに含まれ、プロセス内の実際の操作単位です。プログラマはこれをマルチプロセッサ プログラミングに使用でき、マルチスレッドを使用して計算負荷の高いタスクを高速化できます。 (推奨される調査: Java インタビューの質問)

たとえば、1 つのスレッドがタスクを完了するのに 100 ミリ秒かかる場合、タスクを完了するのに 10 個のスレッドを使用するのにかかる時間はわずか 10 ミリ秒です。 。

スレッドとプロセスの違いは何ですか?

スレッドはプロセスのサブセットです。プロセスには多数のスレッドを含めることができ、各スレッドは異なるタスクを並行して実行します。異なるプロセスは異なるメモリ空間を使用し、すべてのスレッドは同じメモリ空間を共有します。各スレッドには、ローカル データを保存するための個別のスタック メモリがあります。

Java でスレッドを実装するにはどうすればよいですか?

2 つの方法: java.lang.Thread クラスのインスタンスはスレッドですが、実行するには java.lang.Runnable インターフェイスを呼び出す必要があります。スレッド クラス自体が呼び出される Runnable インターフェイスであるため、 、 java.lang.Thread クラスを継承するか、Runnable インターフェースを直接呼び出して run() メソッドをオーバーライドしてスレッドを実装できます。

Java キーワード volatile と synchronized の機能と違いは何ですか?

1、volatile

変更する変数はコピーを保持せず、メイン メモリに直接アクセスします。

Java メモリ モデルにはメイン メモリがあり、各スレッドにも独自のメモリ (レジスタなど) があります。パフォーマンスを向上させるために、スレッドはアクセスする変数のコピーを自身のメモリに保持します。

このように、あるスレッドのメモリ内の同じ変数の値が、ある時点で別のスレッドのメモリ内の値やメイン メモリ内の値と一致しない可能性があります。

変数を volatile として宣言すると、変数はいつでも他のスレッドによって変更されるため、スレッド メモリにキャッシュできなくなります。

2、同期済み

メソッドまたはコード ブロックの変更に使用すると、最大 1 つのスレッドがコードを同時に実行することが保証されます。

1. 2 つの同時スレッドが同じオブジェクト内の synchronized (this) 同期コード ブロックにアクセスする場合、一度に 1 つのスレッドのみを実行できます。別のスレッドは、このコード ブロックを実行する前に、現在のスレッドがこのコード ブロックの実行を完了するまで待つ必要があります。

2. ただし、スレッドがオブジェクトの同期された (この) 同期コード ブロックにアクセスするとき、別のスレッドは引き続きオブジェクト内の非同期 (この) 同期コード ブロックにアクセスできます。

3. 特に重要なのは、スレッドがオブジェクトの同期された (この) 同期されたコード ブロックにアクセスすると、他のスレッドはオブジェクト内の他のすべての同期された (この) 同期されたコード ブロックにアクセスできなくなることです。

4. スレッドがオブジェクトの同期された (この) 同期されたコード ブロックにアクセスすると、このオブジェクトのオブジェクト ロックを取得します。その結果、オブジェクト オブジェクトのすべての同期されたコード部分への他のスレッドのアクセスが一時的にブロックされます。

5. 上記のルールは他のオブジェクト ロックにも適用できます。

さまざまなスレッドのライフ サイクルとは何ですか?

Java プログラムで新しいスレッドを作成すると、そのステータスは New になります。スレッドの start() メソッドを呼び出すと、ステータスが Runnable に変更されます。スレッド スケジューラは、実行可能スレッド プール内のスレッドに CPU 時間を割り当て、ステータスを実行中に変更します。他のスレッド状態には、待機中、ブロック済み、デッドなどがあります。

スレッドの優先順位についてどのように理解していますか?

各スレッドには優先度があり、一般的には優先度の高いスレッドが優先して実行されますが、これはスレッドスケジューリングの実装に依存します。この実装はOSに依存します。

スレッドの優先順位を定義できますが、これは、優先順位の高いスレッドが優先順位の低いスレッドよりも前に実行されることを保証するものではありません。スレッドの優先順位は int 変数 (1 ~ 10) で、1 は最低の優先順位を表し、10 は最高の優先順位を表します。

デッドロックとは何ですか?デッドロックを分析して回避するにはどうすればよいですか?

デッドロックとは、3 つ以上のスレッドが永久にブロックされる状況を指します。この状況には、少なくとも 2 つのスレッドと 3 つ以上のリソースが必要です。

デッドロックを分析するには、Java アプリケーションのスレッド ダンプを表示する必要があります。どのスレッドが BLOCKED ステータスにあり、どのスレッドが待機しているリソースを確認する必要があります。各リソースには一意の ID があり、この ID を使用して、どのスレッドがそのオブジェクト ロックをすでに所有しているかを調べることができます。

ネストされたロックを回避し、必要な場合にのみロックを使用し、無期限の待機を回避することが、デッドロックを回避する一般的な方法です。

スレッド セーフとは何ですか? Vector はスレッドセーフなクラスですか?

コードが配置されているプロセスで同時に複数のスレッドが実行されている場合、これらのスレッドがこのコードを同時に実行する可能性があります。各実行の結果がシングルスレッド実行の結果と同じであり、他の変数の値が予想どおり同じである場合、それはスレッドセーフです。

スレッドセーフ カウンター クラスの同じインスタンス オブジェクトは、複数のスレッドで使用されても計算エラーを引き起こしません。明らかに、コレクション クラスをスレッド セーフと非スレッド セーフの 2 つのグループに分けることができます。 Vector は同期メソッドを使用してスレッド セーフを実現しますが、それに似た ArrayList はスレッド セーフではありません。

Java でスレッドを停止するにはどうすればよいですか?

Java は豊富な API を提供しますが、スレッドを停止するための API は提供しません。 JDK 1.0 には当初、stop()、suspend()、resume() などのいくつかの制御メソッドがありましたが、潜在的なデッドロックの脅威のため、後続の JDK バージョンでは非推奨になりました。その後、Java API の設計者は、互換性のあるスレッドを提供しませんでした。スレッドを停止する安全な方法。

run() または call() メソッドが実行されると、スレッドは自動的に終了します。スレッドを手動で終了したい場合は、volatile Boolean 変数を使用して run() メソッドのループを終了するか、キャンセルすることができます。スレッドの割り込み

ThreadLocal とは何ですか?

ThreadLocal は、スレッドのローカル変数を作成するために使用されます。オブジェクトのすべてのスレッドがそのグローバルを共有することがわかっています。変数なので、これらの変数はスレッドセーフではありませんが、同期技術​​を使用できます。ただし、同期を使用したくない場合は、ThreadLocal 変数を選択できます。

各スレッドには独自の Thread 変数があり、get()\set() メソッドを使用してデフォルト値を取得したり、スレッド内で値を変更したりできます。 ThreadLocal インスタンスは通常、関連するスレッド状態をプライベート静的プロパティにする必要があります。

Sleep()、suspend()、wait() の違いは何ですか?

Thread.sleep() は、指定された時間に現在のスレッドを「実行不可」状態にします。スレッドは常にオブジェクトのモニターを保持します。たとえば、スレッドが現在同期されたブロックまたはメソッド内にある場合、他のスレッドはそのブロックまたはメソッドに入ることができません。別のスレッドがinterrupt() メソッドを呼び出すと、「スリープ」スレッドが起動されます。

注: sleep() は静的メソッドです。これは、現在のスレッドに対してのみ有効であることを意味します。よくある間違いは、t.sleep() を呼び出すことです (t は現在のスレッドとは異なるスレッドです)。

t.sleep() が実行されても、t スレッドではなく、現在のスレッドがスリープ状態になります。 t.suspend() は時代遅れのメソッドです。suspend() を使用すると、スレッドが停滞状態になります。スレッドは常にオブジェクトの監視を保持します。Suspend() はデッドロックの問題を引き起こしやすいです。

Object.wait() は、現在のスレッドを「実行不可能」状態にします。 sleep() との違いは、wait がスレッドではなくオブジェクトのメソッドであることです。 object.wait() を呼び出す場合、スレッドはまずこのオブジェクトのオブジェクト ロックを取得する必要があり、現在のスレッドはロック オブジェクトの同期を維持し、現在のスレッドを待機キューに追加する必要があります。

次に、別のスレッドが同じオブジェクト ロックを同期して object.notify() を呼び出すことができます。これにより、元の待機スレッドがウェイクアップされ、ロックが解放されます。基本的に wait()/notify() は sleep()/interrupt() に似ていますが、前者はオブジェクト ロックを取得する必要がある点が異なります。

スレッド スタベーションとライブロックとは何ですか?

すべてのスレッドがブロックされているか、必要なリソースが無効であるために処理できない場合、リソースを使用可能にする非ブロック スレッドは存在しません。 Java API でのスレッドのライブロックは、次の状況で発生する可能性があります:

1、プログラム内のすべてのスレッドがパラメーター 0 の wait メソッドである Object.wait(0) を実行するとき。プログラムは、スレッドが対応するオブジェクトに対して Object.notify() または Object.notifyAll() を呼び出すまでライブ ロックを続けます。

2: すべてのスレッドが無限ループに陥った場合。

Java Timer クラスとは何ですか?特定の時間間隔でタスクを作成するにはどうすればよいですか?

java.util.Timer は、将来の特定の時刻にスレッドを実行するようにスケジュールするために使用できるツール クラスです。 Timer クラスを使用して、1 回限りのタスクまたは定期的なタスクをスケジュールできます。

java.util.TimerTask は、Runnable インターフェイスを実装する抽象クラスです。独自のスケジュールされたタスクを作成し、Timer を使用してその実行をスケジュールするには、このクラスを継承する必要があります。

Java における同期コレクションと同時コレクションの違いは何ですか?

同期コレクションと同時コレクションはどちらも、マルチスレッドと同時実行に適したスレッドセーフなコレクションを提供しますが、同時コレクションの方がよりスケーラブルです。

Java 1.5 より前は、プログラマは同期コレクションしか使用できませんでした。これにより、マルチスレッドが同時に実行されているときに競合が発生し、システムのスケーラビリティが妨げられていました。

Java5 では、ConcurrentHashMap のような同時コレクションが導入されました。これは、スレッドの安全性を提供するだけでなく、ロックの分離や内部パーティショニングなどの最新のテクノロジーによってスケーラビリティも向上します。

同期メソッドと同期ブロック、どちらがより良い選択ですか?

同期ブロックはオブジェクト全体をロックしないため、より良い選択です (もちろん、オブジェクト全体をロックすることもできます)。同期メソッドは、クラス内に無関係な同期ブロックが複数ある場合でもオブジェクト全体をロックします。これにより、通常、メソッドの実行が停止し、オブジェクトのロックを取得するまで待機する必要があります。

スレッド プールとは何ですか?なぜそれを使うのでしょうか?

スレッドの作成には多くのリソースと時間がかかるため、タスクが来たときだけスレッドを作成すると応答時間が長くなり、プロセスで作成できるスレッドの数が制限されます。

これらの問題を回避するために、プログラム起動時に処理に応答するスレッドを複数用意し、これをスレッドプールと呼び、その中のスレッドをワーカースレッドと呼びます。

JDK1.5 以降、Java API はさまざまなスレッド プールを作成できるように Executor フレームワークを提供します。たとえば、単一のスレッド プールは一度に 1 つのタスクを処理します。固定数のスレッド プールまたはキャッシュ スレッド プール (有効期間の短いタスクが多いプログラムに適した拡張可能なスレッド プール)。

Java の invokeAndWait と invokeLater の違いは何ですか?

これら 2 つのメソッドは、イベント ディスパッチ スレッドではなく現在のスレッドから GUI コンポーネントを更新するために、Swing API によって Java 開発者に提供されます。 InvokeAndWait() は、進行状況バーなどの GUI コンポーネントを同期的に更新します。進行状況が更新されたら、それに応じて進行状況バーも変更する必要があります。

進行状況が複数のスレッドによって追跡されている場合は、invokeAndWait() メソッドを呼び出して、イベント ディスパッチ スレッドにコンポーネントを適宜更新するように要求します。 invokeLater() メソッドは、更新コンポーネントを非同期的に呼び出します。

マルチスレッドにおけるビジー ループとは何ですか?

ビジー ループとは、従来のループとは異なり、プログラマがループを使用してスレッドを待機させることです。 wait()、sleep()、または yield() メソッドはどちらも CPU 制御を放棄しますが、ビジー ループは CPU を放棄せず、空のループを実行します。これの目的は、CPU キャッシュを保持することです。

マルチコア システムでは、待機中のスレッドが起動時に別のコアで実行されている可能性があり、これによりキャッシュが再構築されます。キャッシュの再構築を回避し、再構築の待ち時間を短縮するために使用できます。

以上がJava マルチスレッドに関する面接の質問の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート