Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
主要是:lock.lock();lock.unlock()、condition.await();condition.signal(); 这4个操作的关系
前置:
lock 有一个AQS的同步队列,这是一个双向链表,用于多线程争抢锁。
condition 有一个等待队列,这是一个单向链表,用于await 存储被阻塞的线程。
await、signal操作,只有拿到锁,即lock.lock();才可以调用
阻塞队列模拟流程:
A B线程同时进来时,A抢到锁,则B进入的AQS的同步队列,等待lock.unlock()。
A线程调用await时,则A park 阻塞 并移到等待队列。相当于释放了锁,此时B可能会抢到锁
B线程 调用 signal时,将节点从等待队列转移到AQS尾部,A线程被唤醒,获得之前的锁,继续执行
B线程调用lock.unlock() 后,AB同时取拿锁,返回最初状态
public class CustomerThread implements Runnable{
public Queue<Integer> msg;
public Lock lock;
public Condition condition;
public int maxSize;
public CustomerThread(Queue<Integer> msg, Lock lock, Condition condition, int maxSize) {
this.msg =msg;
this.lock = lock;
this.condition = condition;
this.maxSize = maxSize;
}
@Override
public void run() {
for (;;){
lock.lock();
System.out.println("消费端拿到锁");
if(msg.isEmpty()){//集合满了
try {
System.out.println("消费端await");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费信息:" + msg.remove());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
condition.signal();
lock.unlock();
}
}
}
package com.gupaoedu.circleprint;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @Author qfeng
* @Date 2020/8/1
* @Description TODO
* @Version 1.0
* History: <p>如果有修改过程,请记录</P>
*/
public class ProducerThread implements Runnable{
public Queue msg;
public Lock lock;
public Condition condition;
public int maxSize;
public ProducerThread(Queue<Integer> msg, Lock lock, Condition condition, int maxSize) {
this.msg =msg;
this.lock = lock;
this.condition = condition;
this.maxSize = maxSize;
}
@Override
public void run() {
int i=0;
for (;;){
i++;
lock.lock();
System.out.println("生产端拿到锁");
if(msg.size() == maxSize){//集合满了
try {
System.out.println("生产端await");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
msg.add(i);
System.out.println("生产信息:"+ i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
condition.signal();
lock.unlock();
}
}
}
public class App {
public static void main(String[] args) {
Queue<Integer> msg = new LinkedList();
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int maxSize = 10;
new Thread(new ProducerThread(msg,lock,condition,maxSize)).start();
new Thread(new CustomerThread(msg,lock,condition,maxSize)).start();
}
}