admin管理员组

文章数量:1599721

一、ReentrantLock 的方法介绍

下面列举一些常见的ReentrantLock的方法。

  1. int getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
  2. int getQueueLength():返回正等待获取此锁定的线程估计数。比如有5个线程,1个线程首先执行await()方法,那么在调用getQueueLength方法后返回值是4,说明有4个线程在等待lock的释放。
  3. int getWaitQueueLength(Condition condition):返回等待此锁定相关的给定条件Condition的线程估计数。比如有5个线程,每个线程都执行了同一个condition对象的await方法,则调用getWaitQueueLength(Condition condition)方法时返回的int值是5。
  4. boolean hasQueuedThread(Thread thread):查询指定线程是否正在等待获取此锁定。
  5. boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
  6. boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的condition条件。
  7. boolean isFair():判断是否是公平锁。
  8. boolean isHeldByCurrentThread():查询当前线程是否保持此锁定。
  9. boolean isLocked():查询此锁定是否由任意线程保持。
  10. 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的一些常用方法

     放入数据

  1.  offer(E o, long timeout, TimeUnit unit)方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true;
  2.  put()方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常.
  3.  add()方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException("Queue full");

   获取数据

  1.  peek()方法直接取出队头的元素,并不删除.
  2.  element()方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()
  3.  poll()方法取出并删除队头的元素,当队列为空,返回null;
  4.  take()方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常

   删除数据

    remove()方法直接删除队头的元素;(当队列为空时会抛出NoSuchElementException

   备注:虽然来说LinkedList没有禁止不让添加null,但是一般情况下Queue的实现类都不可以添加null,因为因为 poll(), peek() 方法在异常的时候会返回 null,如果添加null,就无法分辨是什么情况了。

2.阻塞队列的使用

 

本文标签: JavaReentrantLockcondition