admin管理员组文章数量:1599721
一、ReentrantLock 的方法介绍
下面列举一些常见的ReentrantLock的方法。
- 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():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
二、ReentrantLock Condition的使用
两个进程共享一个公共的固定大小的缓冲区(BoundedBuffer)。其中一个是生产者,用于把消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。
问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。
同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。
下面是java提供的一个自己实现阻塞队列的例子。(自己实现阻塞队列还是需要了解一下的)
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
final BoundedBuffer boundedBuffer = new BoundedBuffer();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 run");
for (int i = 0; i < 20; i++) {
try {
System.out.println("putting..");
boundedBuffer.put(Integer.valueOf(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}) ;
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Object val = boundedBuffer.take();
System.out.println(val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}) ;
t1.start();
t2.start();
}
static class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();//写线程条件
final Condition notEmpty = lock.newCondition();//读线程条件
final Object[] items = new Object[15];
int putptr/*写索引*/, takeptr/*读索引*/, count/*队列中存在的数据个数*/;
public void put(Object x) throws InterruptedException {
System .out.println("put wait lock");
lock.lock();
System.out.println("put get lock");
try {
while (count == items.length) {
System.out.println("buffer full, please wait");
notFull.await();
}
items[putptr] = x;
if (++putptr == items.length) {
putptr = 0;
}
++count;
System.out.println("--------------------"+x);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
System.out.println("take wait lock");
lock.lock();
System.out.println("take get lock");
try {
while (count == 0) {
System.out.println("no elements, please wait");
notEmpty.await();
}
System.out.println("--------------------被唤醒");
Object x = items[takeptr];
if (++takeptr == items.length) {
takeptr = 0;
}
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
}
三、阻塞队列学习(java Queue 的学习)
队列Queue的一些常用方法
放入数据
- offer(E o, long timeout, TimeUnit unit)方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true;
- put()方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常.
- add()方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException("Queue full");
获取数据
- peek()方法直接取出队头的元素,并不删除.
- element()方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()
- poll()方法取出并删除队头的元素,当队列为空,返回null;
- take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常
删除数据
remove()方法直接删除队头的元素;(当队列为空时会抛出NoSuchElementException)
备注:虽然来说LinkedList没有禁止不让添加null,但是一般情况下Queue的实现类都不可以添加null,因为因为 poll(), peek() 方法在异常的时候会返回 null,如果添加null,就无法分辨是什么情况了。
2.阻塞队列的使用
本文标签: JavaReentrantLockcondition
版权声明:本文标题:【java学习积累】ReentrantLock Condition的使用 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1728322902a1154058.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论