Lock对象Condition接口实现等待/通知

关键字Synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待通知,ReentrantLock借助Condition对象可以实现同样的功能,而且一个lock对象可以创建多个condition对象,从而能够选择性condition对象进行等待/通知

condition对象实现等待通知的简单案例

public class ConditionLockDemo {
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();
	public void csleep(){
		try{
			lock.lock();
			System.out.println(Thread.currentThread().getName()+"current time :"+System.currentTimeMillis());
			condition.await();
			System.out.println(Thread.currentThread().getName()+"唤醒后 current time :"+System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void signal(){
		try{
			lock.lock();
			condition.signal();
		}finally{
			lock.unlock();
		}
	}
}

启动两个线程,分别调用两个方法

public static void main(String[] args) throws InterruptedException {
	final ConditionLockDemo cl = new ConditionLockDemo();
	Thread a = new Thread(new Runnable() {
		@Override
		public void run() {
			cl.csleep();
		}
	}, "A");
	Thread b = new Thread(new Runnable() {
		@Override
		public void run() {
			cl.signal();
		}
	}, "B");
	a.start();
	Thread.sleep(1000);
	b.start();
}

输出:

Acurrent time :1525329885799
A唤醒后 current time :1525329886799

从这个简单案例:

*  condition 对象是lock对象进行创建的,而且一个lock对象可以创建多个condition对象

*  等待通知的实现,借助condition 对象的await()方法进入阻塞状态释放锁,signal方法唤醒waiting的线程

await()和signal方法的调用必须都要先在获取到锁之后(lock.lock())

condition部分方法描述
方法 描述
await()

当前线程进入waiting状态,并且释放当前线程的锁,当前线程被唤醒,直到其他线程调用signal、signalAll或者interrupt方法

如果线程从await方法返回,表示已经获取到锁

awaitUninterruptibly() 和上面方法一致,区别在于对于其他线程的中断方法不敏感
awaitUntil(Date deadline) 当前线程进入等待状态直到被通知、中断或者到某个时间点,如果没有到时间点就被通知,方法返回true,否则到了指定时间,返回false
signal() 获取到锁后,唤醒处于waiting状态的线程
signalAll() 获取到锁后,唤醒所有处在waiting状态的线程

condition实现生产者消费者模型

3个线程轮流打印1,2,3 。。。

思想:

3个线程,创建3个condition对象

3个线程读取同一个共享变量的值,然后根据值,判断是否进入阻塞状态

,如果不是阻塞状态,修改这个值,并唤醒下一个线程,  A-B-C-A轮流唤醒

public class ThreeConditionDemo {
	private Lock lock = new ReentrantLock();
	private Condition condition1 = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	private Condition condition3 = lock.newCondition();
	private volatile int count = 1;
	public void printA() {
		try{
			lock.lock();
			while(count!=1){
				condition1.await();
			}
			Thread.sleep(1000);
			System.out.println("1");
			count = 2 ;
			condition2.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void printB(){
		try{
			lock.lock();
			while(count!=2){
				condition2.await();
			}
			Thread.sleep(1000);
			System.out.println("2");
			count = 3;
			condition3.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void printC(){
		try{
			lock.lock();
			while(count!=3){
				condition3.await();
			}
			Thread.sleep(1000);
			System.out.println("3");
			count = 1;
			condition1.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
}

启动三个线程测试:

public static void main(String[] args) {
		final ThreeConditionDemo tcd = new ThreeConditionDemo();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printA();
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printB();
				}
			}
		});
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					tcd.printC();
				}
			}
		});
		t1.start();
		t2.start();
		t3.start();
	}
Object监视器锁和Condition方法的对比

对比项 Object监视器方法 Condition
前置条件 获取object对象的锁 调用lock.lock()获取锁
调用方法 object.wait/notify,notifyAll

Condition condition = lock.newCondition()

condition.await/signal,signalAll

释放锁进入等待状态,能够不响应中断 不支持 支持
释放锁进入超时等待 支持 支持
等待队列的个数 1个

多个,lock可以创建多个condition,调用一个condition.await方法

就加入等待队列中


猜你喜欢

转载自blog.csdn.net/ditto_zhou/article/details/80179664
今日推荐