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