簡単な紹介
パートではJavaのマルチスレッドの基礎()我々は、我々は特定のメソッドを見て、方法職場での活用に私たちを許可するこの区別を一般的な方法のいくつかのスレッドを述べました。
メソッドのメソッドを待って通知
ではObject
、クラスの定義wait
方法およびnotify
方法、wait
アクションのメソッドが待機状態に現在のスレッドは、現在のスレッドが置かれるようにすることです预执行队列
、ますwait
の呼び出し、コードはそれが通知または中断されるまで実行方法で停止wait
方法の前に、スレッドが取得する必要がありますオブジェクトをロックし、それだけであることができる同步方法
か、同步代码块
呼び出しwait
方法、および方法は、現在のスレッドのロックが保持しているロックを解除します。notify
ウェイクアップ方法は、現在のオブジェクト上で待機することで单个线程
、スレッドスケジューラが選択されます、待機中の複数のスレッドがある場合は、wait
彼らの問題をスレッドがnotify
それを受信した場合でも、手段対象オブジェクトのロックを取得するために、そして待ちます予告、スレッドはすぐに待つ必要があり、オブジェクトのロックを取得しないnotify
ロックはそれを解放することをスレッド。そして、wait
といった方法notify
方法が唯一にすることができ同步方法
たり同步代码块
、コール。また、同様のアプローチがありnotifyAll
、その役割は、現在のオブジェクトを待機して目を覚ますことです、所有线程
。
プロデューサー次の消費者は、例示しwait
た方法およびnotify
使用方法を:
/**
* @author mghio
* @date: 2019-12-14
* @version: 1.0
* @description: 线程 wait() 和 notify() 方法使用示例
* @since JDK 1.8
*/
public class ThreadWaitAndNotifyDemo {
public static void main(String[] args) {
Producer producer = new Producer();
producer.start();
new Consumer("Consumer One", producer).start();
new Consumer("Consumer Two", producer).start();
new Consumer("Consumer Three", producer).start();
new Consumer("Consumer Four", producer).start();
}
static class Producer extends Thread {
List<String> messageList = new ArrayList<>(2);
@Override
public void run() {
try {
while (true) {
Thread.sleep(2000);
synchronized (messageList) {
String message = String.format("producer message [create time:%s]", LocalDateTime.now());
messageList.add(message);
System.out.println("Producer " + getName() + " producer a msg: " + message);
messageList.notify();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
String getMessage() {
synchronized (messageList) {
if (messageList.size() == 0) {
try {
messageList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return messageList.remove(0);
}
}
}
static class Consumer extends Thread {
private Producer producer;
public Consumer(String name, Producer producer) {
super(name);
this.producer = producer;
}
@Override
public void run() {
while (true) {
String message = producer.getMessage();
System.out.println("Consumer " + getName() + " get a msg: " + message);
}
}
}
}
复制代码
出力:
Producer Thread-0 producer a msg: producer message [create time:2019-12-14T22:45:42.319]
Consumer Consumer One get a msg: producer message [create time:2019-12-14T22:45:42.319]
Producer Thread-0 producer a msg: producer message [create time:2019-12-14T22:45:44.324]
Consumer Consumer Two get a msg: producer message [create time:2019-12-14T22:45:44.324]
Producer Thread-0 producer a msg: producer message [create time:2019-12-14T22:45:46.325]
Consumer Consumer Three get a msg: producer message [create time:2019-12-14T22:45:46.325]
Producer Thread-0 producer a msg: producer message [create time:2019-12-14T22:45:48.328]
Consumer Consumer Four get a msg: producer message [create time:2019-12-14T22:45:48.328]
复制代码
プロデューサーの循環消費者のスレッドの呼び出しgetMessage
メッセージのリストがあれば、メッセージを取得する方法を、messageList
空で、メッセージリストの呼び出しwait
待機状態にスレッドを取得する方法を、メッセージが2秒ごとに生成され、メッセージリストの生産に置かれているmessageList
。への呼び出しが成功した後、notify
この方法は、ウェイクアップであるwait
コールで、留意すべきメッセージ、消費するスレッドの状態wait
とnotify
上記の例の方法は、されたときに最初のオブジェクトのロックを獲得しなければならないsynchronized
コードブロックと呼ばれるが。
睡眠方法
そしてwait
、notify
異なる方法、sleep
で定義されたメソッドThread
メソッド名からクラスは、このメソッドの役割は作ることであることを認識することができ当前线程休眠
、すなわち、メソッドの後から現在のスレッドと呼ばれる运行状态(Running)状态
に入る阻塞(休眠)状态(Blocked)
と、睡眠に時間を与えなければならない、スリープ現在のスレッドこの時間は、指定されたスリープ時間以上になります。スレッドが再び目を覚ますと、スレッド阻塞状态(Blocked)
にターンを就绪状态(Runnable)
して、CPUの実行スケジュールを待ちます。sleep
次のようにメソッドのサンプルコードは、次のとおりです。
/**
* @author mghio
* @date: 2019-12-14
* @version: 1.0
* @description: 线程 sleep() 方法使用示例
* @since JDK 1.8
*/
public class ThreadSleepDemo {
private static Object object = new Object();
public static void main(String[] args) {
MyThread myThreadOne = new MyThread("t1");
MyThread myThreadTwo = new MyThread("t2");
myThreadOne.start();
myThreadTwo.start();
}
static class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
synchronized (object) {
try {
for (int i = 0; i < 5; i++) {
System.out.println(String.format("%s: %d", this.getName(), i));
if (i % 2 == 0) {
Thread.sleep(2000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
复制代码
出力:
t1: 0
t1: 1
t1: 2
t1: 3
t1: 4
t2: 0
t2: 1
t2: 2
t2: 3
t2: 4
复制代码
我々は2つのスレッドを開始したt1
とt2
の二つのスレッドrun
の方法が同じオブジェクトを参照するobject
(同期ロックsynchronized (object)
)、最初のスレッドでけれどもt1
ときi
2回のコールで割り切れるThread.sleep(2000)
スレッドをスリープ2 sまで現在のスレッドを作ることが、今回t2
もので、あなたは、実行するためのCPUを実行するための権利を取得することはできませんt1
呼び出すスレッドsleep
方法が解放されませんobject
開催された同期ロックを。私たちがコメントした場合はsynchronized (object)
、再びプログラムの実施後に、糸t1
とt2
交互として以下のコメントの後に出力され、実行することができます。
t2: 0
t1: 0
t1: 1
t2: 1
t1: 2
t2: 2
t2: 3
t1: 3
t2: 4
t1: 4
复制代码
利回り法
yield
で定義されたメソッドThread
のクラスは、スレッドの具体的な方法です。このアプローチの主な効果は让步
、現在のスレッドからそれを作ることに运行状态(Running)
なり、就绪状态(Runnable)
他の人が同じ優先度を持つように、就绪状态
CPU(への権利を得るために、実行のスレッドPS: CPU 会从众多的处于就绪状态的线程里选择,也就是说,当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到
)、しかし、それは現在のスレッドの呼び出しを保証するものではありませんyield
、他の後に持っていました同じ優先度のスレッドが実装権を取得することができます、現在のスレッドの中に存在し入力することができます运行状态(Running)
実行し続けます。yield
次のようにメソッドのサンプルコードは、次のとおりです。
/**
* @author maguihai
* @date: 2019-12-14
* @version: 1.0
* @description: 线程 yield() 方法使用示例
* @since JDK 1.8
*/
public class ThreadYieldDemo {
public static void main(String[] args) {
MyThread myThreadOne = new MyThread("t1");
MyThread myThreadTwo = new MyThread("t2");
myThreadOne.start();
myThreadTwo.start();
}
static class MyThread extends Thread {
MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(String.format("%s [%d] ---> %d", this.getName(), this.getPriority(), i));
if (i % 2 == 0) {
yield();
}
}
}
}
}
复制代码
出力:
t1 [5] ---> 0
t2 [5] ---> 0
t1 [5] ---> 1
t1 [5] ---> 2
t1 [5] ---> 3
t1 [5] ---> 4
t1 [5] ---> 5
t1 [5] ---> 6
t1 [5] ---> 7
t1 [5] ---> 8
t1 [5] ---> 9
t2 [5] ---> 1
t2 [5] ---> 2
t2 [5] ---> 3
t2 [5] ---> 4
t2 [5] ---> 5
t2 [5] ---> 6
t2 [5] ---> 7
t2 [5] ---> 8
t2 [5] ---> 9
复制代码
上記の出力からわかるように、スレッドt1
の変数がi
2で割り切れること、およびスレッドに切り替わりませんでしたt2
実行する、それはまた、私たちは、上記の、言っ確認yield
あなたがスレッドを作ることができるが、この方法が运行状态
なり就绪状态
、それはない、しかし、それが正しいCPUにそれによって取得した他のスレッドの実行を行います运行状态
、さらに、現在のスレッドと同じ優先度の他、もしyield
真上ロック(この例の証拠を解放しない方法でrun
追加する方法synchronized (obj)
に、この時間t2
スレッドスレッドがするまで、私たちは待っていますt1
、実装後に実行されます)。
メソッドに参加
いくつかのシーンでは、我々はサブスレッド時間のかかる作業の一部で実行する必要があるが、我々はそう、あなたが使用することができ、仕上がり後のエンドまで、メインスレッドと子スレッドの実行を待機しなければならないjoin
方法を、および方法は、で定義されThread
たクラス、メソッド役割は次のとおりです。让主线程等待子线程执行结束之后才能继续执行
例では、見てみましょう:
/**
* @author maguihai
* @date: 2019-12-15
* @version: 1.0
* @description: 线程 join() 方法使用示例
* @since JDK 1.8
*/
public class ThreadJoinDemo {
public static void main(String[] args) {
try {
MyThread myThread = new MyThread("t1");
myThread.start();
myThread.join();
System.out.println(String.format("%s ---> %s finish", LocalDateTime.now(), Thread.currentThread().getName()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread {
MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(String.format("%s ---> %s start", LocalDateTime.now(), this.getName()));
// 模拟耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("%s ---> %s finish", LocalDateTime.now(), this.getName()));
}
}
}
复制代码
出力:
2019-12-15T00:22:55.971 ---> t1 start
2019-12-15T00:22:57.984 ---> t1 finish
2019-12-15T00:22:57.985 ---> main finish
复制代码
メインスレッドでmain
通じnew MyThread("t1")
新しいスレッドt1
。次に、t1.start()
スレッドを開始しt1
、実行t1.join()
しますメインスレッドを入力した後に阻塞状态
待つt1
実行の終了を。子供が糸t1
の端を、それは、CPUを実行するための権利を再取得するためにメインスレッドをメインスレッドを覚ますだろう、メインスレッドがダウンして実行し続けます。使用してjoin
、メインスレッドの終了後に次のような方法は終了する子スレッドを待ちます。
概要
これらは、導入されたいくつかの一般的なスレッド方法や具体的な知識の概要を使用しています。