生产消费模型
ReentrantLock提供了tryLock方法,tryLock调用的时候,如果锁被其他线程持有,那么tryLock会立即返回,返回结果为false;如果锁没有被其他线程持有,那么当前调用线程会持有锁,并且tryLock返回的结果为true。
对于ReentrantLock来说,还有一个十分实用的特性,它可以同时绑定多个Condition条件,以实现更精细化的同步控制。
ReentrantLock使用方式如下:
Lock lock = new ReentrantLock();
lock.lock();
try{
}finally{
lock.unlock();
}
- int getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
- int getQueueLength():返回正等待获取此锁定的线程估计数。比如有5个线程,1个线程首先执行await()方法,那么在调用getQueueLength方法后返回值是4,说明有4个线程在等待lock的释放。
- int getWaitQueueLength(Condition condition):返回等待此锁定相关的给定条件Condition的线程估计数。比如有5个线程,每个线程都执行了同一个condition对象的await方法,则调用getWaitQueueLength(Condition condition)方法时返回的int值是5。
- boolean hasQueuedThread(Thread thread):查询指定线程是否正在等待获取此锁定。
- boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
- boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的condition条件。
- boolean isFair():判断是不是公平锁。
- boolean isHeldByCurrentThread():查询当前线程是否保持此锁定。
- boolean isLocked():查询此锁定是否由任意线程保持。
- void lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
public class ProducerConsumerByLock {
private static final int CAPACITY = 5;
private static final Lock lock = new ReentrantLock();
private static final Condition fullCondition = lock.newCondition(); //队列满的条件
private static final Condition emptyCondition = lock.newCondition(); //队列空的条件
public static void main(String args[]){
Queue<Integer> queue = new LinkedList<Integer>();
Thread producer1 = new Producer("P-1", queue, CAPACITY);
Thread producer2 = new Producer("P-2", queue, CAPACITY);
Thread consumer1 = new Consumer("C1", queue, CAPACITY);
Thread consumer2 = new Consumer("C2", queue, CAPACITY);
Thread consumer3 = new Consumer("C3", queue, CAPACITY);
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
consumer3.start();
}
/**
* 生产者
*/
public static class Producer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
int i = 0;
public Producer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
//获得锁
lock.lock();
while(queue.size() == maxSize){
try {
System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
//条件不满足,生产阻塞
fullCondition.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("[" + name + "] Producing value : +" + i);
queue.offer(i++);
//唤醒其他所有生产者、消费者
fullCondition.signalAll();
emptyCondition.signalAll();
//释放锁
lock.unlock();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
*/
public static class Consumer extends Thread{
private Queue<Integer> queue;
String name;
int maxSize;
public Consumer(String name, Queue<Integer> queue, int maxSize){
super(name);
this.name = name;
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run(){
while(true){
//获得锁
lock.lock();
while(queue.isEmpty()){
try {
System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
//条件不满足,消费阻塞
emptyCondition.await();
} catch (Exception ex) {
ex.printStackTrace();
}
}
int x = queue.poll();
System.out.println("[" + name + "] Consuming value : " + x);
//唤醒其他所有生产者、消费者
fullCondition.signalAll();
emptyCondition.signalAll();
//释放锁
lock.unlock();
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
LinkedBlockingQueue
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;//private final ReentrantLock putLock = new ReentrantLock();
final AtomicInteger count = this.count;//private final AtomicInteger count = new AtomicInteger();
putLock.lockInterruptibly();//如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
try {
while (count.get() == capacity) {
notFull.await();//如果达到设置的总量则执行满锁等待
}
enqueue(node);//Node<E> last = last.next = node;添加到队列最后
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();//队列个数不超过总数时释放满锁对应notify
} finally {
putLock.unlock();//解锁putLock
}
if (c == 0)
signalNotEmpty();//解锁空锁
}
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;//private final AtomicInteger count = new AtomicInteger();
final ReentrantLock takeLock = this.takeLock;//private final ReentrantLock takeLock = new ReentrantLock();
takeLock.lockInterruptibly();//如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
try {
while (count.get() == 0) {//队列空时进行等待
notEmpty.await();
}
x = dequeue();//从队列头部取出一个值
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();//个数大于一说明还可以继续取所以唤醒空锁
} finally {
takeLock.unlock();//解锁takeLock
}
if (c == capacity)
signalNotFull();
return x;
}
这两段代码可以看出来,ReentrantLock相当于synchronized的作用锁住这段代码不能同时被多线程访问,而Condition则提供唤醒等待机制。一个Condition对应一个等待和一个解锁,使用是:在当前线程不满足业务条件时候等待,其他线程满足业务条件了释放唤醒该条件。
引用:https://blog.csdn.net/u010983881/article/details/78554671