欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lock的使用:Condition实现等待/通知

程序员文章站 2022-03-09 19:00:50
...

关键字synchronized与wait()和notify()/notify()方法结合可以实现等待/通知模式,当然ReentrantLock可以实现这样的功能,只不过需要借助一个叫Condition的对象。Condition对象会有着更好的灵活性,比如实现多路通知,也就是在一个Lock对象里面创建多个Condition实例,线程对象可以注册在一个指定的Condition中,从而可以进行有选择的通知,而不是像synchronized那样靠JVM的随机选择。选择性通知这个非常重要,而且实在Condition类中默认提供的。
举例说明
MyService类:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyService {
	
	private Lock lock = new ReentrantLock();
	
	public Condition c = lock.newCondition();
	
	public void await() {
		try {
		lock.lock();
		System.out.println("await时间为 " + System.currentTimeMillis());
		c.await();//相当于synchronized的wait方法
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
			System.out.println("运行时间为" + System.currentTimeMillis());
		}
	}
	
	public void signal() {
		lock.lock();
		System.out.println("signal时间为 " + System.currentTimeMillis());
		c.signal();//相当于synchronized的notify方法
		lock.unlock();
	}
}

ThreadA类:

public class ThreadA extends Thread{
	
	private MyService service;
	
	public ThreadA(MyService service) {
		super();
		this.service = service;
	}
	
	public void run() {
		service.await();
	}
}

跑一下类:

public class Run {
	public static void main(String[] args) throws InterruptedException {
		MyService service = new MyService();
		ThreadA a = new ThreadA(service);
		a.start();
		Thread.sleep(3000);
		service.signal();
	}
}

运行结果:

await时间为 1554891059865
signal时间为 1554891062865
运行时间为1554891062868

成功实现类似于synchronized的wait/notify模式。
前言介绍了Condition对象可以唤醒部分指定线程,这样有助于提升程序运行的效率。可以先对线程进行分组,然后再唤醒指定组中的线程,所以再创建个项目举例说明

MyService类:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyService {
	
	private Lock lock = new ReentrantLock();
	
	public Condition cA = lock.newCondition();
	
	public Condition cB = lock.newCondition();
	
	public void awaitA() {
		try {
		lock.lock();
		System.out.println("begin awaitA时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		cA.await();//相当于synchronized的wait方法
		System.out.println("end awaitA时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void awaitB() {
		try {
		lock.lock();
		System.out.println("begin awaitB时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		cB.await();//相当于synchronized的wait方法
		System.out.println("end awaitB时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void signalAll_A() {
		lock.lock();
		System.out.println(" signalAll_A时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		cA.signalAll();
		lock.unlock();
	}
	
	public void signalAll_B() {
		lock.lock();
		System.out.println(" signalAll_B时间为 " + System.currentTimeMillis()
		+ " ThreadName " + Thread.currentThread().getName());
		cB.signalAll();
		lock.unlock();
	}
}

ThreadA类:

public class ThreadA extends Thread{
	
	private MyService service;
	
	public ThreadA(MyService service) {
		super();
		this.service = service;
	}
	
	public void run() {
		service.awaitA();
	}
}

ThreadB类:

public class ThreadB extends Thread{
	
	private MyService service;
	
	public ThreadB(MyService service) {
		super();
		this.service = service;
	}
	
	public void run() {
		service.awaitB();
	}
}

跑一下类:

public class Run {
	public static void main(String[] args) throws InterruptedException {
		MyService service = new MyService();
		ThreadA a = new ThreadA(service);
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB(service);
		b.setName("B");
		b.start();
		Thread.sleep(3000);
		service.signalAll_A();
	}
}

运行结果:

begin awaitA时间为 1554958541855 ThreadName A
begin awaitB时间为 1554958541855 ThreadName B
 signalAll_A时间为 1554958544856 ThreadName main
end awaitA时间为 1554958544856 ThreadName A

由结果可以看出,ReentrantLock对象可以唤醒指定的线程。

相关标签: Lock