-
关键字synchronized与wait/notify这两个方法一起使用,可以实现等待/通知模式。lock锁的newCondition()方法会返回Condition对象,Condition类也可以实现等待/通知模式。
-
使用notify通知时,JVM会随机唤醒某个等待的线程,使用Condition类可以进行选择行通知。Condition比较常用的两个方法:
- await()会使当前线程等待,同时会释放锁,当其他线程调用signal()时,线程会重新获得锁行继续执行.
- signal()用于唤醒一个等待的线程
注意:
在调用Condition的await/signal方法前,也需要线程持有相关的lock锁,调用await后线程会释放这个锁,在signal调用后会从当前Condition对象的等待队列中,唤醒一个线程,唤醒的线程会尝试获得锁,一旦获得锁成功就会继续执行
一、Condition实现等待与通知
dome
package com.dome.lock.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author qb
* @version 1.0
* @Description
* Condition 等待与通知
* @date 2021/3/11 11:20
*/
public class Test01 {
//定义锁
static Lock lock = new ReentrantLock();
//获得Condition对象
static Condition condition = lock.newCondition();
//定义线程子类
static class SubThread extends Thread{
@Override
public void run() {
try {
lock.lock(); //在调用await方法前先获取锁
System.out.println("method lock");
condition.await();
System.out.println("method await");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
System.out.println("method unlock");
}
}
}
public static void main(String[] args) {
SubThread subThread = new SubThread();
subThread.start();
//子线程启动后,会转入等等待状态
try {
//主线程睡眠3秒,唤醒子线程
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
lock.lock();
condition.signal();
} finally {
lock.unlock();
}
}
}
二、使用多个Condition实现通知部分线程
使用更灵活
dome
package com.dome.lock.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author qb
* @version 1.0
* @Description
* 多个condition通知部分线程
* @date 2021/3/11 11:29
*/
public class Test02 {
static class Service{
//定义锁对象
private ReentrantLock lock = new ReentrantLock();
//定义两个Condition对象
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
//定义方法使conditionA等待
public void waitMethodA(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" 开始等待 "+System.currentTimeMillis());
conditionA.await();
System.out.println(Thread.currentThread().getName()+"结束等待"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//定义方法使conditionB等待
public void waitMethodB(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" 开始等待 "+System.currentTimeMillis());
conditionB.await();
System.out.println(Thread.currentThread().getName()+"结束等待"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//定义方法唤醒conditionA的等待
public void signalA(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +" signal A time = "+System.currentTimeMillis());
conditionA.signal();
System.out.println(Thread.currentThread().getName()+" signal * A time = "+System.currentTimeMillis());
} finally {
lock.unlock();
}
}
//定义方法唤醒conditionB的等待
public void signalB(){
try {
lock.lock();
System.out.println(Thread.currentThread().getName() +" signal B time = "+System.currentTimeMillis());
conditionB.signal();
System.out.println(Thread.currentThread().getName()+" signal * B time = "+System.currentTimeMillis());
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
Service service = new Service();
//开启两个线程,分别调用
new Thread(new Runnable() {
@Override
public void run() {
service.waitMethodA();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
service.waitMethodB();
}
}).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//华兴 A 上的等待
service.signalA();
}
}
三、 使用Condition实现生产者/消费者而设计模式, 两个线程交替打印
dome
package com.dome.lock.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author qb
* @version 1.0
* @Description
* 使用Condition实现生产者/消费者而设计模式, 两个线程交替打印
* @date 2021/3/11 11:41
*/
public class Tetst03 {
static class MyService{
private Lock lock = new ReentrantLock(); //创建锁对象
private Condition condition = lock.newCondition(); //创建Condition对象
private boolean flag = true ; ///定义打印标志
//定义方法但因 ---横线
public void printOne(){
try {
lock.lock();
while (flag){ //为ture等待
System.out.println(Thread.currentThread().getName()+"wait.....");
condition.await();
}
System.out.println(Thread.currentThread().getName() + "-------");
flag = true;
condition.signal(); //通知另外线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//定义方法但因 ***横线
public void printTwo(){
try {
lock.lock();
while (!flag){ //为false等待
System.out.println(Thread.currentThread().getName()+"wait.....");
condition.await();
}
System.out.println(Thread.currentThread().getName() + "******");
flag = false;
condition.signal(); //通知另外线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
MyService myService = new MyService();
//创建线程打印--
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
myService.printOne();
}
}
}).start();
//创建线程打印**
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
myService.printTwo();
}
}
}).start();
}
}
四、Condition实现多对多的生产者消费者模式
dome
package com.dome.lock.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author qb
* @version 1.0
* @Description
* 使用Condition实现生产者/消费者而设计模式, 多线程交替打印
* @date 2021/3/11 11:41
*/
public class Tetst04 {
static class MyService{
private Lock lock = new ReentrantLock(); //创建锁对象
private Condition condition = lock.newCondition(); //创建Condition对象
private boolean flag = true ; ///定义打印标志
//定义方法但因 ---横线
public void printOne(){
try {
lock.lock();
while (flag){ //为ture等待
System.out.println(Thread.currentThread().getName()+"wait.....");
condition.await();
}
System.out.println(Thread.currentThread().getName() + "----------");
flag = true;
//condition.signal(); //通知另外线程打印
condition.signalAll(); //通知另外线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//定义方法但因 ***横线
public void printTwo(){
try {
lock.lock();
while (!flag){ //为false等待
System.out.println(Thread.currentThread().getName()+"wait.....");
condition.await();
}
System.out.println(Thread.currentThread().getName() + "**********");
flag = false;
//condition.signal(); //通知另外线程打印
condition.signalAll(); //通知另外线程打印
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
MyService myService = new MyService();
for (int i = 0; i < 10; i++) {
//创建线程打印--
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
myService.printOne();
}
}
}).start();
//创建线程打印**
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
myService.printTwo();
}
}
}).start();
}
//结果造成假死 解决 将 signal换成 signalAll
}
}