ホームページ  >  記事  >  Java  >  Java マルチスレッドに関する一般的な面接の質問

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

(*-*)浩
(*-*)浩オリジナル
2019-12-24 15:02:402450ブラウズ

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

並列処理と同時実行の違いは何ですか? (推奨される調査: java の一般的な面接の質問 )

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

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

複数のタスクを 1 つのプロセッサーで「同時に」処理し、複数のタスクを複数のプロセッサーで同時に処理します。 Hadoop分散クラスタなど。

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

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

つまり、プロセスはプログラムの実行とリソース割り当ての基本単位であり、プログラムには少なくとも 1 つのプロセスがあり、プロセスには少なくとも 1 つのスレッドがあります。プロセスには実行中に独立したメモリ ユニットがあり、複数のスレッドがメモリ リソースを共有するため、切り替え回数が削減され、効率が向上します。

スレッドはプロセスの実体であり、CPU のスケジューリングとディスパッチの基本単位であり、プログラムよりも小さく独立して実行できる基本単位です。同じプロセス内の複数のスレッドは同時に実行できます。

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

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

スレッドを作成するにはどのような方法がありますか?

①. Thread クラスを継承してスレッド クラスを作成します

Thread クラスのサブクラスを定義し、クラスの run メソッドをオーバーライドします run メソッドのメソッド本体はスレッドの要件、完了したタスク。したがって、run() メソッドは実行本体と呼ばれます。

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

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

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

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

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

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

③. Callable と Future によるスレッドの作成

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

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

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

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

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

これは少し深い質問であり、Java プログラマーが取得できる知識の広さを示しています。

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

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

スレッドのステータスは何ですか?

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

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

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

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

ブロッキング状態。スレッドの実行中は、通常、実行を続行する前に一定時間待機する (たとえば、特定のリソースの準備が整う) ため、スレッドは一時停止されます。スリープ、サスペンド、待機などのメソッドはスレッドのブロックを引き起こす可能性があります。

死亡状態。スレッドの run メソッドが終了するか stop メソッドが呼び出されると、スレッドは終了します。スレッドが停止した場合、start メソッドを使用してスレッドを準備することはできなくなります。

sleep(): このメソッドはスレッド クラス (Thread) の静的メソッドであり、呼び出し元のスレッドがスリープ状態に入り、他のスレッドに実行の機会を与えます。完了すると、スレッドは準備完了状態になり、他のスレッドが CPU 実行時間を競い合います。

sleep() は静的メソッドであるため、オブジェクトのマシン ロックを変更できません。sleep() メソッドが同期ブロック内で呼び出された場合、スレッドはスリープ状態になりますが、オブジェクトのマシン ロックは解放されません。他のスレッドはまだこのオブジェクトにアクセスできません。

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

notify() と NoticeAll() の違いは何ですか?

スレッドがオブジェクトの wait() メソッドを呼び出した場合、スレッドはオブジェクトの待機プール内に存在し、待機プール内のスレッドはオブジェクトのロックをめぐって競合しません。

スレッドがオブジェクトのnotifyAll()メソッド(すべての待機スレッドをウェイクアップ)またはnotify()メソッド(ランダムに1つの待機スレッドのみをウェイクアップ)を呼び出すと、ウェイクアップされたスレッドはオブジェクトのロック・プールに入ります。ロック プール内のスレッドはオブジェクト ロックをめぐって競合します。

つまり、notify を呼び出した後、1 つのスレッドだけが待機プールからロック プールに入り、notifyAll はオブジェクト待機プール内のすべてのスレッドをロック プールに移動して、ロックの競合を待機します。

優先度の高いスレッドは、オブジェクト ロックをめぐって競合する可能性が高くなります。スレッドがオブジェクト ロックをめぐって競合しない場合、そのスレッドはロック プールに残ります。スレッドが wait() メソッドを呼び出した場合のみです。また待機プールに戻ります。

オブジェクト ロックを競合するスレッドは、同期されたコード ブロックが実行されるまで実行を継続し、オブジェクト ロックを解放します。この時点で、ロック プール内のスレッドは、オブジェクト ロックをめぐって競合し続けます。オブジェクトロック。

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

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

start() メソッドを使用してスレッドを開始し、真のマルチスレッド操作を実現します。このとき、run メソッド本体のコードが実行されるのを待つ必要はなく、直接次のコードの実行を続行できますが、この時点ではスレッドは準備完了状態にあり、実行されていません。

次に、この Thread クラスを通じてメソッド run() を呼び出して、実行ステータスを完了します。ここでのメソッド run() はスレッド本体と呼ばれ、実行されるスレッドのコンテンツが含まれます。Run メソッドは終了しますそしてスレッドの終了。次に、CPU は他のスレッドをスケジュールします。

run() メソッドはこのスレッドにありますが、これはスレッド内の単なる関数であり、マルチスレッドではありません。 run() を直接呼び出す場合、実際には通常の関数を呼び出すのと同じです。run() メソッドを直接使用する場合は、次のコードを実行する前に run() メソッドの実行が完了するまで待つ必要があります。まだ実行パスが 1 つだけであり、スレッドがまったくないという特性があるため、マルチスレッド実行時には run() メソッドの代わりに start() メソッドを使用する必要があります。

スレッド プールを作成するにはどのような方法がありますか?

①.newFixedThreadPool(int nThreads)

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

②. newCachedThreadPool()

キャッシュ可能なスレッド プールを作成します。スレッド プールのサイズが処理需要を超えた場合、アイドル状態のスレッドは自動的にリサイクルされます。需要が増加すると、アイドル状態のスレッドは再利用されます。新しいスレッドを追加する場合、スレッド プールのサイズに制限はありません。

③. newSingleThreadExecutor()

これはシングルスレッドのエグゼキュータであり、タスクを実行する単一のワーカー スレッドを作成します。このスレッドが異常終了した場合、新しいスレッドが作成されて置き換えられます。 ; it 特徴は、タスクがキュー内の順序に従ってシリアルに実行されることを保証することです。

④. newScheduledThreadPool(int corePoolSize)

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

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

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

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

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

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

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

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

submit は例外処理を容易にします

In Java プログラム マルチスレッド操作の安全性を確保するにはどうすればよいですか?

スレッドの安全性は 3 つの側面に反映されます。

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

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

秩序性: 1 つのスレッドが他のスレッドを監視します。スレッド内の命令の実行は、命令の並べ替えにより、一般に組織化されていません (事前発生の原則)。

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

Java には 4 つのロック状態があります。低レベルから高レベルまで: ステートレス ロック、バイアス ロック、軽量ロック、重量ロック状態です。これらの状態は時間とともに変化します。競争が徐々に進むにつれて、エスカレートします。ロックはアップグレードできますが、ダウングレードはできません。

ロックのアップグレードのプロセスの図解:

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

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

デッドロックとは、2 つ以上のプロセスが実行中にリソースの競合や通信を行うことによって発生するブロック現象のことで、外部からの力がなければ、すべてのプロセスが処理を進めることができなくなります。このとき、システムがデッドロック状態にある、またはシステムがデッドロックに陥っているといい、このように常に待ち合っているプロセスをデッドロックプロセスと呼びます。

はオペレーティング システム レベルのエラーであり、プロセス デッドロックの略語です。これは、1965 年にバンカー アルゴリズムを研究する際にダイクストラによって最初に提案されました。コンピュータ オペレーティング システムで対処するのが最も困難であり、同時プログラミングの分野全体における質問の 1 つです。

デッドロックを防ぐにはどうすればよいですか?

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

相互排他条件: プロセスが、割り当てられたリソースへの他のプロセスのアクセスを許可しない。リソースの場合、リソースを占有しているプロセスが使用を完了してリソースを解放するまで待つことしかできません。

リクエストと保持の条件: プロセスは特定のリソースを取得した後、他のリソースをリクエストしますが、リソースは他のプロセスによって占有されている場合、このリクエストはブロックされますが、取得したリソースは保持されます。

非剥奪条件: プロセスが取得したリソースを指します。使用が完了するまで剥奪することはできません。

#ループ待機条件: プロセスのデッドロックが発生した後、複数のプロセス間で先頭から末尾までのループ待機リソース関係を形成する 4 つの条件を指します

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

デッドロックの理由、特にデッドロックに必要な 4 つの条件を理解すると、デッドロックを可能な限り回避、防止、排除することができます。

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

さらに、プロセスが待機状態にあるときにリソースを占有しないようにすることも必要です。したがって、リソースの割り当ては適切に計画する必要があります。

ThreadLocal とは何ですか?どのような使用シナリオがありますか?

スレッドローカル変数は、スレッド自体に属し、複数のスレッド間で共有されない、スレッドに限定された変数です。 Java は、スレッド セーフを実現する方法であるスレッド ローカル変数をサポートする ThreadLocal クラスを提供します。

ただし、ワーカー スレッドのライフ サイクルがアプリケーション変数のライフ サイクルよりも長い管理環境 (Web サーバーなど) でスレッド ローカル変数を使用する場合は特に注意してください。

作業の完了後にスレッドローカル変数が解放されないと、Java アプリケーションはメモリ リークの危険にさらされます。

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

Synchronized を使用すると、メソッドまたはコード ブロックの実行中に、同時にクリティカル セクションに入ることができるのは 1 つのメソッドだけであることが保証され、共有変数のメモリの可視性も保証されます。

Java のすべてのオブジェクトはロックとして使用でき、これが同期を実現するための synchronized の基礎となります:

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

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

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

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

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

volatile は変数レベルでのみ使用でき、synchronized は変数、メソッド、クラス レベルで使用できます。

volatile は変数の変更の可視性のみを実現でき、アトミック性は保証できませんが、synchronized は変数の変更の可視性とアトミック性を保証できます。

Volatile ではスレッド ブロックが発生しませんが、synchronized ではスレッド ブロックが発生する可能性があります。

volatile とマークされた変数はコンパイラによって最適化されませんが、synchronized とマークされた変数はコンパイラによって最適化できます。

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

まず、synchronized は Java の組み込みキーワードです。JVM レベルでは、Lock は Java クラスです。

synchronized では、ロック状態が取得されているかどうかを判断できません。ただし、Lock はロックが取得されているかどうかを判断できます。

synchronized は自動的にロックを解放します (スレッドは同期コードの実行後にロックを解放します。スレッドは実行中に例外が発生した場合にロックを解放します)。Lock最終的に手動で解放する必要があります (unlock() メソッドがロックを解放します)。そうしないと、スレッドのデッドロックが簡単に発生します。

2 つのスレッド 1 と 2 に synchronized キーワードを使用します。現在のスレッド 1 の場合、ロックを取得すると、スレッド 2 は待機します。スレッド 1 がブロックされている場合、スレッド 2 は永久に待機し、Lock ロックは必ずしも待機する必要はありません。ロックを取得できない場合、スレッドは待機せずに終了できます。

同期ロックは繰り返すことができます。入力可能、中断不可、 Lock は再入可能で、判断可能で、公平です (両方が可能です)。

Lock ロックは大量の同期コードによる同期の問題に適しており、同期ロックは少量のコードに適しています。 . 同期の問題。

同期ロックとリエントラントロックの違いは何ですか?

synchronized は if、else、for、while と同じキーワードであり、ReentrantLock はクラスです。これが 2 つの本質的な違いです。

ReentrantLock はクラスであるため、synchronized よりも柔軟な機能が提供されます。継承でき、メソッドを持つことができ、さまざまなクラス変数を持つことができます。ReentrantLock は synchronized よりも拡張性があります。いくつかの点で:

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

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

ReentrantLock は複数の通知を柔軟に実装できます

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

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

Atomic パッケージのクラスの基本的な特徴は、マルチスレッド環境で、複数のスレッドが 1 つの変数 (基本型と参照型を含む) を同時に操作するときに、つまり、複数のスレッドがこの変数の値を同時に更新すると、1 つのスレッドだけが成功し、失敗したスレッドは実行が成功するまでスピン ロックのように試行を続けることができます。

Atomic シリーズのクラスのコア メソッドは、安全でないクラスのいくつかのローカル メソッドを呼び出します。最初に知っておく必要があるのは、Unsafe クラスです。そのフルネームは sun.misc.Unsafe です。このクラスには、多くの直接メモリ割り当てやアトミック操作の呼び出しなど、C コードに対する多数の操作が含まれています。は安全ではないとマークされていますが、この中の多数のメソッド呼び出しにはセキュリティ上のリスクがあり、注意して使用する必要があり、そうでないと重大な結果につながる可能性があることをお伝えします。たとえば、安全でない方法でメモリを割り当てる場合、特定の領域を指定すると、C のような結果になる可能性があります。ポインタが他のプロセスへの境界を越えます。

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

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。