syncronizedキーワードと待機()およびNOTIFY()とのnotifyAll()がのawait通知クラスReentrantLockのも同じ機能を実現することができます達成しますが、ヘルプ条件を必要とすることができ、このクラスは、ロックオブジェクトに言っている複数の通知を実装することができます複数のインスタンス(オブジェクト・モニタ)を作成することができる条件は、スレッドオブジェクトは、指定された条件に登録することができるようにすることができます選択スレッドより柔軟なスケジューリングに通知スレッド。
そしてsyncronized全体の条件の一つだけ相当のnotifyAll(とき)を開始し、あなたがすべての待機中のスレッドに通知する必要があり、選択の余地がないすべてのスレッドがスレッドの上にに登録されている、ロックオブジェクトをオブジェクトに、リソースの無駄があるでしょう。以下は、デモデモ条件間違った用法です。
public class Demo1 {
private Lock lock = new ReentrantLock ();
private Condition condition = lock.newCondition ();
public void await(){
try {
condition.await ();
} catch (InterruptedException e) {
e.printStackTrace ();
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1 ();
new Thread (() -> {
demo1.await ();
}).start ();
}
}
エラーを実行した後:そのため、私たちは、waitメソッドを使用して、同期モニタを取得するためにlock.lock()を呼び出し覚えておくCondition.awiat()またはシングル()メソッドのニーズを呼び出す前にsynctonized理由などのキーワードの使用を要求することです
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2036)
at Lock.KodyLockTest.ConditionStudy.Demo1.await(Demo1.java:19)
at Lock.KodyLockTest.ConditionStudy.Demo1.lambda$main$0(Demo1.java:28)
at java.lang.Thread.run(Thread.java:748)
ダブルスレッド間通信のケース
public class Demo1 {
private Lock lock = new ReentrantLock ();
private Condition condition = lock.newCondition ();
public void await(){
try {
lock.lock ();
System.out.println (Thread.currentThread ().getName () + "线程获得锁");
condition.await ();
} catch (InterruptedException e) {
e.printStackTrace ();
}finally {
System.out.println (Thread.currentThread ().getName () + "线程释放锁");
lock.unlock ();
}
}
public void single(){
lock.lock ();
System.out.println (Thread.currentThread ().getName () + "线程获得锁");
condition.signal ();
System.out.println (Thread.currentThread ().getName () + "线程唤醒睡眠线程");
lock.unlock ();
System.out.println (Thread.currentThread ().getName () + "线程释放锁");
}
public static void main(String[] args) throws InterruptedException{
Demo1 demo1 = new Demo1 ();
new Thread (() -> {
demo1.await ();
}).start ();
TimeUnit.SECONDS.sleep (3);
new Thread (() -> {
demo1.single ();
}).start ();
}
}
コンソール情報:0最初のスレッドが価値が条件に登録され、ここで待っている待機中のスレッドプールまで(ロック手段は、オブジェクトのロックをあきらめる)ロックを取得するための待機に入り、スレッド1をつかんされた後、スレッド1次ウェイク後スレッド、一つのスレッドだけ0があると、それは、目を覚ますスレッド0が目覚めたので、目を覚ますが、あなたは、コードの実行を継続する必要があります再びロックスレッド0オブジェクトのロックを取得するために必要な、これはリリースによって異なりますが、スレッド1を解放しませんでした、リリースされ、その後、0をスレッド化してリリースし、最終的に実行した後に、コードを実行し、グラブ、ロックをつかむために続けています。ここで覚えておくべきことの一つがされたスレッドは、スレッド1と0は、あなたが再びロックをつかむために覚えておく必要があるため、すぐに、コードを実行し、実行することはできません目を覚ます、あなたが目を覚ましするロックを取得する必要があります。
Thread-0线程获得锁
Thread-1线程获得锁
Thread-1线程唤醒睡眠线程
Thread-1线程释放锁
Thread-0线程释放锁
交互デュアルスレッド実行
交互に実施される条件オブジェクト識別子に加えて実行]を使用
package Lock.KodyLockTest.ConditionStudy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Heian
* @time 19/10/13 16:13
* @description:线程一打印循环打印 我爱你 线程2打印 肖体秀
*/
public class Demo2 {
private static Lock lock = new ReentrantLock ();
private static Condition condition = lock.newCondition ();
//设置一个标识符,如果某个线程打印了则修改标识符位,让自身处于等待,同理另一个线程可以打印
private static Boolean flag = false;//因为用了线程同步,所以该字面修改是线程可见的
public static void main(String[] args) {
new Thread (() -> {
lock.lock ();
for (int i=0;i<100;i++){
try {
while (flag == true){
condition.await ();
}
System.out.println ("我爱你");
TimeUnit.SECONDS.sleep (1);
flag = true;
condition.signal ();
}catch (InterruptedException e){
e.printStackTrace ();
}
}
lock.unlock ();
}).start ();
new Thread (() -> {
lock.lock ();
for (int i=0;i<100;i++){
try {
while (flag == false){
condition.await ();
}
System.out.println ("肖体秀");
TimeUnit.SECONDS.sleep (1);
flag = false;
condition.signal ();
}catch (InterruptedException e){
e.printStackTrace ();
}
}
lock.unlock ();
}).start ();
}
}
スレッドのライフサイクルの終わりのために二つの条件オブジェクトの実装は、それがすぐにロックを解除し、ないにもスレッドが待っていることを可能に!= 10裁判官を追加しました
package Lock.KodyLockTest.ConditionStudy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Heian
* @time 19/10/13 16:13
* @description:线程一打印循环打印 我爱你 线程2打印 肖体秀
*/
public class Demo3 {
private static Lock lock = new ReentrantLock ();
private static Condition conditionA = lock.newCondition ();
private static Condition conditionB = lock.newCondition ();
private static AtomicInteger atomicIntegerA = new AtomicInteger (0);
private static AtomicInteger atomicIntegerB = new AtomicInteger (0);
public static void main(String[] args) {
new Thread (() -> {
lock.lock ();
for (int i=0;i<10;i++){
try {
TimeUnit.SECONDS.sleep (1);
System.out.println ("我爱你");
conditionB.signal ();//在进入等待池之前先唤醒B,此时A的锁并没有释放
if ( atomicIntegerA.incrementAndGet () != 10){
conditionA.await ();//如果不是最后一个需要你睡眠,是最后一次的话就直接unlock
}
}catch (InterruptedException e){
e.printStackTrace ();
}
}
lock.unlock ();
}).start ();
new Thread (() -> {
lock.lock ();
for (int i=0;i<10;i++){
try {
TimeUnit.SECONDS.sleep (1);
System.out.println ("肖体秀");
conditionA.signal ();//在进入等待池之前先唤醒A,此时B的锁并没有释放
if ( atomicIntegerB.incrementAndGet () != 10){
conditionB.await ();
}
}catch (InterruptedException e){
e.printStackTrace ();
}
}
lock.unlock ();
}).start ();
}
}
三件の以上のスレッドが交互に行われており、実行の順序
私はを参照することができます行っ交互場合:https://blog.csdn.net/qq_40826106/article/details/86607122 ケース7ここで私は、実行順序が同じであることを、スレッドの終了、プラスライン上で、独自のマニュアルを判断してはいけません。
ここで、ランダム変数NUMによって、そのスレッドの実行順序を指定するために、3つのスレッドを実行する:3つのスレッドのランダムなスタートは、最初のB、BがCを開始し、その後想定ブロッキングであろうと仮定起動時に実行がAを起動するとき、Cは、ブロッキングであろうこれは、Bが動作ABC順を達成するために、ウェイクCを実行し、Bを呼び起こします。
package Lock.KodyLockTest.ConditionStudy;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Heian
* @time 19/10/13 16:13
* @description: 线程顺序执行
*/
public class Demo4 {
private static Lock lock = new ReentrantLock ();
private static Condition conditionA = lock.newCondition ();
private static Condition conditionB = lock.newCondition ();
private static Condition conditionC = lock.newCondition ();
private static int num = 1;
public static void main(String[] args) {
Thread threadA = new Thread (() -> {
try {
lock.lock ();
while (num != 1) {
conditionA.await ();
}
System.out.println ("我爱你肖体秀1");
num = 2;//事情做完了,就赋值为2
conditionB.signal ();
} catch (InterruptedException e) {
e.printStackTrace ();
} finally {
lock.unlock ();
}
});
Thread threadB = new Thread (() -> {
try {
lock.lock ();
while (num != 2) {
conditionB.await ();
}
System.out.println ("我爱你肖体秀2");
num = 3;
conditionC.signal ();
} catch (InterruptedException e) {
e.printStackTrace ();
} finally {
lock.unlock ();
}
});
Thread threadC = new Thread (() -> {
try {
lock.lock ();
while (num != 3) {
conditionC.await ();
}
System.out.println ("我爱你肖体秀3");
num = 3;
conditionA.signal ();
} catch (InterruptedException e) {
e.printStackTrace ();
} finally {
lock.unlock ();
}
});
threadB.start ();
threadA.start ();
threadC.start ();
}
}