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对象可以唤醒指定的线程。
推荐阅读
-
加入切面环绕通知实现,日志比较完善的使用方式
-
Shell脚本实现硬盘空间和表空间的使用情况统计并邮件通知
-
详解Condition的await和signal等待/通知机制
-
Android中使用Notification实现状态栏的通知
-
【Java用法】使用Java开发连接钉钉应用实现钉钉通知的功能
-
vue 使用element-ui中的Notification自定义按钮并实现关闭功能以及如何处理多个通知
-
使用 Java 的 Lock 锁实现办公楼中的电梯载客程序
-
vue 使用element-ui中的Notification自定义按钮并实现关闭功能及如何处理多个通知
-
不使用synchronized和lock,如何实现一个线程安全的单例
-
Linux C++ 使用condition实现阻塞队列的方法