public class JUCTest02 {
public static void main(String[] args) throws InterruptedException {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
//判斷是否等待,業務,幹完活通知
class Data2 {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increment() throws InterruptedException {
lock.lock();
try {
while (number > 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition.await();
}
number++;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number <= 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition.await();
}
number--;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
編寫代碼時注意順序,首先是lock.lock(),然後try 裏面包括業務邏輯,最後finally lock.unlock()
Condition也是JUC包下接口,可以通過lock.newCondition()進行實例化。
Condition中await,signal ,signalAll方法,對應Object的wait,notify,notifyAll方法。
上述代碼樣例打印的部分結果如下所示
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
Await
B執行了-1;number=0
Bwait
雖然滿足0,1輸出,但是怎麼保證ABCD也是按照順序打印呢?
其實只要創建多個condition對象,就可以精確等待和喚醒了。如下圖代碼所示:
public class JUCTest02 {
public static void main(String[] args) throws InterruptedException {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement4();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
//判斷是否等待,業務,幹完活通知
class Data2 {
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
Condition condition4 = lock.newCondition();
public void increment1() throws InterruptedException {
lock.lock();
try {
while (number > 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition1.await();
}
number++;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement2() throws InterruptedException {
lock.lock();
try {
while (number <= 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition2.await();
}
number--;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void increment3() throws InterruptedException {
lock.lock();
try {
while (number > 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition3.await();
}
number++;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了+1" + ";number=" + number);
condition4.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decrement4() throws InterruptedException {
lock.lock();
try {
while (number <= 0) {
//等待
System.out.println(Thread.currentThread().getName() + "wait");
condition4.await();
}
number--;
//通知其他線程,我+1完畢了
System.out.println(Thread.currentThread().getName() + "執行了-1" + ";number=" + number);
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
部分打印結果,如下所示:
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait
A執行了+1;number=1
Await
B執行了-1;number=0
Bwait
C執行了+1;number=1
Cwait
D執行了-1;number=0
Dwait