Java マルチスレッドと同時実行の基本に関するインタビューの質問と回答

伊谢尔伦
リリース: 2016-11-25 10:45:17
オリジナル
1538 人が閲覧しました

マルチスレッドと同時実行性の質問は、Java テクノロジーの面接で面接官が好んで尋ねる質問の 1 つです。ここでは、面接の観点から重要な質問のほとんどを列挙していますが、今後遭遇する問題に対処するために、Java マルチスレッドの基本知識をしっかりと理解しておく必要があります。

Javaマルチスレッド面接の質問

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

プロセスとは独立した(自己完結型の)実行環境であり、プログラムまたはアプリケーションとみなすことができます。スレッドはプロセス内で実行されるタスクです。 Java ランタイム環境は、さまざまなクラスとプログラムを含む単一のプロセスです。スレッドは軽量プロセスと呼ぶことができます。スレッドは、プロセス内での作成と常駐に必要なリソースが少なくて済み、プロセス内でリソースを共有できます。

2. マルチスレッドプログラミングの利点は何ですか?

マルチスレッドプログラムでは、プログラムの効率を高めるために複数のスレッドが同時に実行されますが、スレッドはリソースを待つ必要があるため、CPUはアイドル状態になりません。複数のスレッドはヒープ メモリを共有するため、複数のプロセスを作成するよりも、いくつかのタスクを実行するために複数のスレッドを作成する方が適切です。たとえば、サーブレットはマルチスレッドをサポートしますが、CGI はサポートしないため、サーブレットは CGI よりも優れています。

3. ユーザースレッドとデーモンスレッドの違いは何ですか?

Javaプログラムでスレッドを作成するとき、それをユーザースレッドと呼びます。デーモン スレッドはバックグラウンドで実行され、JVM の終了を妨げないスレッドです。ユーザー スレッドが実行されていない場合、JVM はプログラムを閉じて終了します。デーモン スレッドによって作成された子スレッドは、依然としてデーモン スレッドです。

4. スレッドはどのように作成しますか?

スレッドを作成するには 2 つの方法があります。1 つは Runnable インターフェイスを実装し、それを Thread コンストラクターに渡して Thread オブジェクトを作成する方法で、もう 1 つは Thread クラスを直接継承する方法です。さらに詳しく知りたい場合は、Java でスレッドを作成する方法に関するこの記事を読んでください。

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

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

6. Threadクラスのrun()メソッドを直接呼び出すことはできますか?

もちろんですが、Thread の run() メソッドを呼び出すと、通常のメソッドと同じように動作します。新しいスレッドでコードを実行するには、Thread.start() メソッドを使用する必要があります。

7. 実行中のスレッドを一定期間一時停止するにはどうすればよいですか?

Thread クラスの Sleep() メソッドを使用して、スレッドを一定期間一時停止できます。これによってスレッドが終了するわけではないことに注意してください。スレッドがスリープから復帰すると、スレッドのステータスは実行可能に変更され、スレッドのスケジュールに従って実行されます。

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

各スレッドには優先順位があり、一般的には優先順位の高いスレッドが優先して実行されますが、これはスレッドスケジューリングの実装に依存します。スレッドの優先順位を定義できますが、これは、優先順位の高いスレッドが優先順位の低いスレッドよりも前に実行されることを保証するものではありません。スレッドの優先順位は int 変数 (1 ~ 10) で、1 は最低の優先順位を表し、10 は最高の優先順位を表します。

9. スレッドスケジューラとタイムスライスとは何ですか?

スレッドスケジューラは、実行可能状態のスレッドにCPU時間を割り当てる責任を負うオペレーティングシステムサービスです。スレッドを作成して開始すると、その実行はスレッド スケジューラの実装に依存します。タイム スライシングとは、利用可能な CPU 時間を利用可能な実行可能スレッドに割り当てるプロセスを指します。 CPU 時間の割り当ては、スレッドの優先順位またはスレッドの待機時間に基づいて行うことができます。スレッドのスケジューリングは Java 仮想マシンによって制御されないため、アプリケーションが制御することをお勧めします (つまり、プログラムをスレッドの優先順位に依存させないでください)。

10. マルチスレッドにおけるコンテキスト切り替えとは何ですか?

コンテキストスイッチングは、CPUの状態を保存および復元するプロセスであり、これにより、スレッドの実行が中断された時点から実行を再開できるようになります。コンテキストの切り替えは、マルチタスク オペレーティング システムおよびマルチスレッド環境に不可欠な機能です。

11. main() メソッドが配置されているスレッドが Java プログラム内で終了する最後のスレッドであることを確認するにはどうすればよいですか?

Threadクラスのjoint()メソッドを使用すると、main()メソッドが終了する前にプログラムによって作成されたすべてのスレッドが確実に終了するようにできます。 Threadクラスのjoint()メソッドについての記事です。

12. スレッドはどのように相互に通信しますか?

スレッドがリソースを共有できる場合、スレッド間通信はそれらを調整する重要な手段です。 Object クラスの wait()notify()notifyAll() メソッドを使用すると、リソース ロックのステータスについてスレッド間で通信できます。スレッド wait、notify、notifyAll の詳細については、ここをクリックしてください。

13. スレッド通信メソッド wait()、notify()、notifyAll() が Object クラスで定義されているのはなぜですか?

Java のすべてのオブジェクトにはロック (モニター、モニターになることもできます) があり、wait() や Notify() などのメソッドは、オブジェクトのロックを待機したり、オブジェクトのモニターがロックされていることを他のスレッドに通知したりするために使用されます。利用可能。 Java スレッド内のオブジェクトに対して使用できるロックやシンクロナイザーはありません。これが、これらのメソッドが Object クラスの一部である理由であり、Java のすべてのクラスにはスレッド間通信のための基本的なメソッドがあります

14. wait()、notify()、notifyAll() が同期メソッド内にある必要がある理由、または同期メソッドである必要があるのはなぜですかブロック 呼ばれていますか?

スレッドがオブジェクトの wait() メソッドを呼び出す必要がある場合、スレッドはオブジェクトのロックを所有する必要があり、その後、他のスレッドがオブジェクトの notify() メソッドを呼び出すまで、オブジェクトのロックを解放して待機状態に入ります。同様に、スレッドがオブジェクトのnotify()メソッドを呼び出す必要がある場合、スレッドはオブジェクトのロックを解放し、待機中の他のスレッドがオブジェクトのロックを取得できるようにします。これらのメソッドはすべて、スレッドがオブジェクトのロックを保持する必要があり、これは同期によってのみ実現できるため、同期メソッドまたは同期ブロック内でのみ呼び出すことができます。

15. Threadクラスのsleep()メソッドとyield()メソッドはなぜstaticなのでしょうか?

Threadクラスのsleep()メソッドとyield()メソッドは、現在実行中のスレッド上で実行されます。したがって、待機している他のスレッドでこれらのメソッドを呼び出すことは意味がありません。このため、これらのメソッドは静的です。これらは現在実行中のスレッドで動作し、プログラマがこれらのメソッドを他の非実行スレッドで呼び出すことができると誤って考えるのを防ぐことができます。

16. スレッドの安全性を確保するにはどうすればよいですか?

Java でスレッド セーフを確保するには、同期、アトミック同時クラスの使用、同時ロックの実装、volatile キーワードの使用、不変クラスとスレッド セーフ クラスの使用など、多くの方法があります。詳細については、スレッド セーフティのチュートリアルをご覧ください。

17. Javaにおけるvolatileキーワードの役割は何ですか?

volatile キーワードを使用して変数を変更すると、スレッドは変数をキャッシュせずに直接読み取ります。これにより、スレッドによって読み取られる変数がメモリ内の変数と一致することが保証されます。

18. 同期メソッドと同期ブロックはどちらが良い選択ですか?

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

19. デーモンスレッドを作成するにはどうすればよいですか?

スレッドをデーモンスレッドとして設定するには、Thread クラスの setDaemon(true) メソッドを使用します。このメソッドは、start() メソッドを呼び出す前に呼び出す必要があることに注意してください。そうしないと、IllegalThreadStateException がスローされます。

20. ThreadLocal とは何ですか?

ThreadLocal は、スレッドのローカル変数を作成するために使用されます。そのため、これらの変数はスレッドセーフではないことがわかっています。ただし、同期を使用したくない場合は、ThreadLocal 変数を選択できます。

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

21. スレッドグループとは何ですか?なぜそれを使用することが推奨されるのですか?

ThreadGroupは、スレッドグループに関する情報を提供することを目的としたクラスです。

ThreadGroup API は比較的弱く、Thread よりも多くの機能を提供しません。これには 2 つの主な機能があります。1 つはスレッド グループ内のアクティブなスレッドのリストを取得すること、もう 1 つはスレッドにキャッチされなかった例外ハンドラー (ncaught 例外ハンドラー) を設定することです。ただし、Java 1.5 では、Thread クラスに setUncaughtExceptionHandler(UncaughtExceptionHandler eh) メソッドも追加されたため、ThreadGroup は廃止されたため、引き続き使用することはお勧めできません。

t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){
 
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("exception occured:"+e.getMessage());
}
 
});
ログイン後にコピー

22. Java スレッド ダンプ (Thread Dump) とは何か、またその取得方法は何ですか?

スレッドダンプはJVMアクティブスレッドのリストで、システムのボトルネックやデッドロックを分析するのに非常に役立ちます。スレッド ダンプを取得するには、プロファイラー、Kill -3 コマンド、jstack ツールなどを使用するさまざまな方法があります。 jstack ツールは使いやすく、JDK が付属しているため、私はこれを好みます。これはターミナルベースのツールであるため、分析用のスレッド ダンプを定期的に生成するスクリプトを作成できます。スレッド ダンプの生成について詳しくは、このドキュメントをお読みください。

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

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

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

ネストされたロックを回避し、必要な場合にのみロックを使用し、無期限の待機を回避することが、デッドロックを回避する一般的な方法です。デッドロックを分析する方法については、この記事をお読みください。

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

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

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

Java Timerの例を示します。

25. スレッドプールとは何ですか? Java スレッド プールを作成するにはどうすればよいですか?

スレッドプールはワーカースレッドのグループを管理し、実行待ちのタスクを配置するためのキューも含まれます。

java.util.concurrent.Executors は、スレッドプールを作成するための java.util.concurrent.Executor インターフェースの実装を提供します。スレッド プールの例では、スレッド プールを作成して使用する方法を示します。または、ScheduledThreadPoolExecutor の例を読んで、定期タスクの作成方法を学習します。

Java同時実行面接の質問

1. アトミック操作とは何ですか? Java Concurrency API のアトミック クラスとは何ですか?

アトミック操作とは、他の操作の影響を受けない操作タスク単位を指します。アトミック操作は、マルチスレッド環境でのデータの不整合を回避するために必要な手段です。

int++はアトミックな操作ではないため、あるスレッドがその値を読み取って1を加算すると、別のスレッドが前の値を読み取ってエラーが発生する可能性があります。

この問題を解決するには、加算操作がアトミックであることを保証する必要があります。JDK1.5 より前では、同期テクノロジーを使用してこれを行うことができました。 JDK 1.5 の時点では、java.util.concurrent.atomic パッケージは、操作がアトミックであることを自動的に保証し、同期の使用を必要としない int 型および long 型のロード クラスを提供します。 Java のアトミック クラスについて学ぶには、この記事を読むことができます。

2. Java Concurrency API の Lock インターフェースとは何ですか?同期と比較した場合の利点は何ですか?

Lock インターフェイスは、同期メソッドや同期ブロックよりもスケーラブルなロック操作を提供します。これらにより、完全に異なるプロパティを持つことができるより柔軟な構造が可能になり、条件付きオブジェクトの複数の関連クラスをサポートできます。

その利点は次のとおりです:

はロックをより公平にすることができます

はロックを待機している間にスレッドを割り込みに応答させることができます

はスレッドにロックの取得を試行させ、ロックを取得できない場合はすぐに戻るか、一定期間待機させることができます

ロックは、さまざまなスコープおよびさまざまな順序で取得および解放できます

ロックの例をもっと読む

3. Executor フレームワークとは何ですか?

Executor フレームワークと java.util.concurrent.Executor インターフェースは Java 5 で導入されました。 Executor フレームワークは、一連の実行戦略に従って呼び出され、スケジュールされ、実行され、制御される非同期タスクのフレームワークです。

無制限にスレッドを作成すると、アプリケーションのメモリがオーバーフローします。したがって、スレッド プールを作成する方が、スレッドの数を制限でき、これらのスレッドをリサイクルして再利用できるため、より良い解決策となります。 Executor フレームワークを使用してスレッド プールを作成すると、非常に便利です。Executor フレームワークを使用してスレッド プールを作成する方法については、この記事をお読みください。

4. ブロッキングキューとは何ですか?ブロッキング キューを使用してプロデューサー/コンシューマー モデルを実装するにはどうすればよいですか?

java.util.concurrent.BlockingQueueの特徴は、キューが空の場合はキューから要素を取得または削除する操作がブロックされ、キューがいっぱいの場合はキューに要素を追加する操作がブロックされます。ブロックされる。

ブロッキングキューはnull値を受け入れません。キューにnull値を追加しようとすると、NullPointerExceptionがスローされます。

ブロッキングキューの実装はスレッドセーフであり、すべてのクエリメソッドはアトミックであり、内部ロックまたは他の形式の同時実行制御を使用します。

BlockingQueue インターフェースは Java コレクション フレームワークの一部であり、主にプロデューサーとコンシューマーの問題を実装するために使用されます。

ブロッキング キューを使用してプロデューサーとコンシューマーの問題を実装する方法については、この記事を読んでください。

5. Callable と Future とは何ですか?

Java 5 では、同時実行パッケージに java.util.concurrent.Callable インターフェースが導入されましたが、Runnable インターフェースに非常によく似ていますが、オブジェクトを返したり、例外をスローしたりできます。

Callableインターフェイスはジェネリックスを使用して戻り値の型を定義します。 Executors クラスは、スレッド プール内の Callable 内でタスクを実行するための便利なメソッドをいくつか提供します。 Callable タスクは並列であるため、それが返す結果を待つ必要があります。 java.util.concurrent.Future オブジェクトは、この問題を解決します。スレッド プールが Callable タスクを送信すると、Future オブジェクトが返されます。これを使用して、Callable タスクのステータスを確認し、Callable によって返される実行結果を取得できます。 Future は、Callable が終了するのを待ってその実行結果を取得できるように get() メソッドを提供します。

Callable、Future の例について詳しくは、この記事をお読みください。

6. FutureTaskとは何ですか?

FutureTaskはFutureの基本的な実装であり、Executorと組み合わせて非同期タスクを処理することができます。通常、FutureTask クラスを使用する必要はありませんが、Future インターフェイスの一部のメソッドをオーバーライドし、元の基本実装を維持することを計画している場合には、このクラスが非常に役立ちます。それを継承して、必要なメソッドをオーバーライドするだけです。その使用方法については、Java FutureTask の例を読んでください。

7. 同時コンテナの実装とは何ですか?

Java コレクション クラスはフェイルファストです。つまり、コレクションが変更され、スレッドが反復子を使用してコレクションを走査すると、反復子の next() メソッドが ConcurrentModificationException 例外をスローします。

同時コンテナは、同時トラバーサルと同時更新をサポートします。

主なクラスは ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet です。ConcurrentModificationException を回避する方法については、この記事をお読みください。

8. Executorsクラスとは何ですか?

Executor は、Executor、ExecutorService、ScheduledExecutorService、ThreadFactory、および Callable クラスにいくつかのツール メソッドを提供します。

Executorを使用すると、スレッドプールを簡単に作成できます。


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!