Javaマルチスレッドではできない面接問題
47381 ワード
目次1.はじめに 2.本文 2.1 Threadクラスのstart()メソッドとrun()メソッドの違いは何ですか? 2.2スレッドの実行順序の制御方法 2.3マルチスレッドでの並列と同時の区別方法 2.4 JavaでCPUを指定してスレッドを実行できますか? 2.5プロジェクト開発において、Javaスレッドの優先度を考慮しますか? 2.6 sleep()メソッドとwait()メソッドの違いは何ですか? 2.7 Javaでスレッドの実行をどのように中断しますか? 2.8現在のスレッドにCPUの実行権をどのように譲るか. 2.9 sleep()、wait()、いったいその関数が割り込みマークをクリアするのか? 3.最後 参考 1.はじめに
マルチスレッド関連の面接問題は基礎的ですが、高周波面点です.
ここで1篇の文章を書いてまとめて、結局、“紙の上で結局浅く感じなければならなくて、絶対にこの事を知ってお辞儀をします”.
2.本文
2.1 Threadクラスのstart()メソッドとrun()メソッドの違いは何ですか?
所属違い:
2.2スレッドの実行順序をどのように制御しますか?
プレゼンテーションコードを参照してください.
実行して、実行結果を確認します.
複数回実行すると、スレッドの実行順序が一致しません.
同じ情報を印刷できるプログラムを複数回実行します.
印刷結果:
2.3マルチスレッド内の並列と同時をどのように区別しますか?
パラレル(Parallel)は「並列実行」または「同時実行」であり、ある時点で、コンピュータオペレーティングシステムでは、1組のプログラムが独立した非同期の速度で実行され、ミクロでもマクロでもプログラムが一緒に実行されることを指す.コンカレント(Concurrent)とは、1つの時間帯にいくつかのプログラムが起動して実行されるまでの間にあり、これらのプログラムは同じプロセッサ上で実行されますが、いずれの時点でも1つのプログラムだけがプロセッサ上で実行されます.
簡単に言えば、
同時、複数の任務が、同じ時間帯に発生したということです.並行して、複数のタスクが、同じ時点で発生したということです.
2.4 JavaでCPUを指定してスレッドを実行できますか?
いいえ、Javaはできません.唯一介入できるのはC言語がカーネルのAPIを呼び出して指定することです.
CPUは,オペレーティングシステムのマルチスレッドに対応してシステムの計算効率を向上させるためである.しかし、各カーネルにタスクを具体的に割り当てるのはJAVAとJVMではなくオペレーティングシステムです.つまり、あなたが実行しているマルチスレッドは、同じCPUカーネルに割り当てられて実行される可能性があります.異なるCPUで動作しない場合もあります.CPUの割り当てを制御できれば、オペレーティングシステムのapiで実現できるはずです.
2.5プロジェクト開発の過程で、Javaスレッドの優先度を考慮しますか?
Javaスレッドの優先度を考慮しますが、Javaスレッドの優先度には依存しません.
優先度の低いスレッドは、実行頻度が低いだけで、優先度の低いスレッドが優先度の高いスレッドよりも必ず実行されるわけではありません.
Javaでは、優先度が10個あります.
しかし、多くのオペレーティングシステムとうまくマッピングできません.たとえば、Windowsには7つの優先度があり、固定されていません.信頼できるのは、優先度を調整するときに、
2.6 sleep()メソッドとwait()メソッドの違いは何ですか?所属違い: 同期中、CPUの実行権とロックの処理が異なる: 呼び出しの場合異なる:
2.7 Javaでは、スレッドの実行をどのように中断しますか?
次のデモコードを見てください.
印刷結果:
2.8現在のスレッドにCPUの実行権をどのように譲るか.
呼び出し
なお、このメソッドを呼び出すのはスケジューラに信号を送るだけであり、現在のスレッドはCPUの実行権を譲りたいと考えている.しかし、スケジューラはこの信号を無視することができます.
2.9 sleep()、wait()、いったいその関数は割り込みマークをクリアしますか?
実行中は常に印刷されます.
印刷ログ:
3.最後に
本文は学生たちのマルチスレッドに対する学習を深めることを望んでいる.
リファレンス並行と並行の違い 『Javaプログラミング思想』 javaスレッド割込みのいくつかの点についてsleep()やwait()などJDK内蔵のメソッド割込み異常を投げてスレッドの割込み状態をクリアする
マルチスレッド関連の面接問題は基礎的ですが、高周波面点です.
ここで1篇の文章を書いてまとめて、結局、“紙の上で結局浅く感じなければならなくて、絶対にこの事を知ってお辞儀をします”.
2.本文
2.1 Threadクラスのstart()メソッドとrun()メソッドの違いは何ですか?
所属違い:
start()
方法はThread
類が自ら宣言する方法、run()
方法はThread
類がRunnable
インターフェースから実現したもの位置決めの違い:Thread
オブジェクトで呼び出すstart()
メソッドがスレッドを作成して開くことができ、start()
メソッドが呼び出されたからこそ、スレッドは無から有へ、有から起動へとなる.start()
メソッド内部で呼び出されるstart0()
これnative
メソッド.run()
メソッドは実行する必要があるコードをカプセル化しただけで、これは一般的なメソッドにもある機能です.呼び出しの違い:スレッドを開くときstart()
メソッドは手動で呼び出す必要がありますがrun()
メソッドは仮想マシンで呼び出されます.2.2スレッドの実行順序をどのように制御しますか?
プレゼンテーションコードを参照してください.
class Task1 implements Runnable {
public Task1() {
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
public class Demo {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Task1(), "Thread " + i);
thread.start();
}
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
実行して、実行結果を確認します.
main is doing task.
Thread 1 is doing task.
Thread 0 is doing task.
Thread 2 is doing task.
Thread 4 is doing task.
Thread 3 is doing task.
複数回実行すると、スレッドの実行順序が一致しません.
Thread
クラスのjoin()
メソッドを使用してスレッドの実行順序を制御できます.class Task2 implements Runnable {
private Thread joiner;
public Task2(Thread joiner) {
this.joiner = joiner;
}
@Override
public void run() {
try {
joiner.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
public class JoinDemo {
public static void main(String[] args) {
Thread joiner = Thread.currentThread();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Task2(joiner), "Thread " + i);
thread.start();
joiner = thread;
}
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
同じ情報を印刷できるプログラムを複数回実行します.
main is doing task.
Thread 0 is doing task.
Thread 1 is doing task.
Thread 2 is doing task.
Thread 3 is doing task.
Thread 4 is doing task.
join()
メソッドの意味はthread2
で呼び出されるthread1.join()
、thread2
待たなければならないthread1
運転完了後に続行するthread2
の運転.なお、呼び出しthread1.join()
メソッドは、thread2
のrun()
メソッドに書かなければならないものではありません.次の例を見てください.class Task3 implements Runnable {
public Task3() {
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
public class JoinDemo2 {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Task3(), "Thread " + i);
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " is doing task.");
}
}
印刷結果:
Thread 0 is doing task.
Thread 1 is doing task.
Thread 2 is doing task.
Thread 3 is doing task.
Thread 4 is doing task.
main is doing task.
2.3マルチスレッド内の並列と同時をどのように区別しますか?
パラレル(Parallel)は「並列実行」または「同時実行」であり、ある時点で、コンピュータオペレーティングシステムでは、1組のプログラムが独立した非同期の速度で実行され、ミクロでもマクロでもプログラムが一緒に実行されることを指す.コンカレント(Concurrent)とは、1つの時間帯にいくつかのプログラムが起動して実行されるまでの間にあり、これらのプログラムは同じプロセッサ上で実行されますが、いずれの時点でも1つのプログラムだけがプロセッサ上で実行されます.
簡単に言えば、
同時、複数の任務が、同じ時間帯に発生したということです.並行して、複数のタスクが、同じ時点で発生したということです.
2.4 JavaでCPUを指定してスレッドを実行できますか?
いいえ、Javaはできません.唯一介入できるのはC言語がカーネルのAPIを呼び出して指定することです.
CPUは,オペレーティングシステムのマルチスレッドに対応してシステムの計算効率を向上させるためである.しかし、各カーネルにタスクを具体的に割り当てるのはJAVAとJVMではなくオペレーティングシステムです.つまり、あなたが実行しているマルチスレッドは、同じCPUカーネルに割り当てられて実行される可能性があります.異なるCPUで動作しない場合もあります.CPUの割り当てを制御できれば、オペレーティングシステムのapiで実現できるはずです.
2.5プロジェクト開発の過程で、Javaスレッドの優先度を考慮しますか?
Javaスレッドの優先度を考慮しますが、Javaスレッドの優先度には依存しません.
優先度の低いスレッドは、実行頻度が低いだけで、優先度の低いスレッドが優先度の高いスレッドよりも必ず実行されるわけではありません.
Javaでは、優先度が10個あります.
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
しかし、多くのオペレーティングシステムとうまくマッピングできません.たとえば、Windowsには7つの優先度があり、固定されていません.信頼できるのは、優先度を調整するときに、
MAX_PRIORITY
、NORM_PRIORITY
とMIN_PRIORITY
の3つのレベルを使うだけです.2.6 sleep()メソッドとwait()メソッドの違いは何ですか?
sleep()
はいThread
クラスの静的メソッド、wait()
はいObject
クラスのメソッド// Thread
public static native void sleep(long millis) throws InterruptedException;
// Object
public final native void wait(long timeout) throws InterruptedException;
public final void wait() throws InterruptedException {
wait(0);
}
wait()
方法CPUの実行権を解放し、ロックを解放する.sleep()
方法CPU実行権を解放し、ロックを解除しない.sleep()
メソッドはどこでも呼び出すことができる;wait()
メソッドは同期でのみ呼び出すことができ、同期で呼び出さないと投げ出されるIllegalMonitorStateException
.2.7 Javaでは、スレッドの実行をどのように中断しますか?
Thread
のstop()
メソッドは使用しないでください.このメソッドは@Deprecated
と表記されています.公式にはThread
のinterrupt()
メソッドを使用して割り込み信号を出すことをお勧めします.これはコラボレーション式の割り込みです.次のデモコードを見てください.
public class UseInterrupt2 {
private static class MyThread extends Thread {
@Override
public void run() {
while (!isInterrupted()) {
System.out.println(Thread.currentThread().getName() + " is running, " +
"isInterrupted() = " + isInterrupted());
}
System.out.println(Thread.currentThread().getName() + " end, " +
"isInterrupted() = " + isInterrupted());
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// main , myThread interrupt() , myThread
myThread.interrupt();
}
}
印刷結果:
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 end, isInterrupted() = true
2.8現在のスレッドにCPUの実行権をどのように譲るか.
呼び出し
Thread.yield()
メソッド:public static native void yield();
なお、このメソッドを呼び出すのはスケジューラに信号を送るだけであり、現在のスレッドはCPUの実行権を譲りたいと考えている.しかし、スケジューラはこの信号を無視することができます.
2.9 sleep()、wait()、いったいその関数は割り込みマークをクリアしますか?
sleep()
メソッドは割り込みフラグをクリアする:public class UseInterrupt3 {
private static class MyThread extends Thread {
@Override
public void run() {
while (!isInterrupted()) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + " sleep interrupted, " +
"isInterrupted() = " + isInterrupted());
}
System.out.println(Thread.currentThread().getName() + " is running, " +
"isInterrupted() = " + isInterrupted());
}
System.out.println(Thread.currentThread().getName() + " end, " +
"isInterrupted() = " + isInterrupted());
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// main , myThread interrupt() , myThread
myThread.interrupt();
}
}
実行中は常に印刷されます.
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.java.advanced.features.concurrent.stopthread.interrupt.UseInterrupt3$MyThread.run(UseInterrupt3.java:9)
Thread-0 sleep interrupted, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
...// Thread-0 is running, isInterrupted() = false
wait()
方法でも割り込みフラグがクリアされる:public class UseInterrupt4 {
private static class MyThread extends Thread {
private Object lock = new Object();
@Override
public void run() {
synchronized (lock) {
while (!isInterrupted()) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + " wait interrupted, " +
"isInterrupted() = " + isInterrupted());
}
System.out.println(Thread.currentThread().getName() + " is running, " +
"isInterrupted() = " + isInterrupted());
}
System.out.println(Thread.currentThread().getName() + " end, " +
"isInterrupted() = " + isInterrupted());
}
}
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// main , myThread interrupt() , myThread
myThread.interrupt();
}
}
印刷ログ:
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.java.advanced.features.concurrent.stopthread.interrupt.UseInterrupt4$MyThread.run(UseInterrupt4.java:11)
Thread-0 wait interrupted, isInterrupted() = false
Thread-0 is running, isInterrupted() = false
3.最後に
本文は学生たちのマルチスレッドに対する学習を深めることを望んでいる.
リファレンス