package com.study.communication;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LockRes {
public String userName;
public String sex;
//true生产者线程等待,false消费者线程生产,生产者可以写,消费者变为等待
public boolean flag = false;
Lock lock = new ReentrantLock();//jdk1.5并发包lock锁
}
/**
* 读
*/
@SuppressWarnings("Duplicates")
class LockOut extends Thread {
LockRes lockRes;
Condition newCondition;
LockOut(LockRes lockRes, Condition newCondition) {
this.lockRes = lockRes;
this.newCondition = newCondition;
}
@Override
public void run() {
int count = 0;
while (true) {
try {
lockRes.lock.lock();//表示开始上锁
if (lockRes.flag) {
try {
//让线程等待
newCondition.await();
} catch (Exception e) {
e.printStackTrace();
}
}
if (count == 0) {
lockRes.userName = "小红";
lockRes.sex = "女";
} else {
lockRes.userName = "小王";
lockRes.sex = "男";
}
count = (count + 1) % 2;
lockRes.flag = true;
newCondition.signal();//唤醒
} catch (Exception e) {
e.printStackTrace();
} finally {
lockRes.lock.unlock();
}
}
}
}
/**
* 写
*/
class LockInput extends Thread {
LockRes lockRes;
Condition newCondition;
LockInput(LockRes res, Condition newCondition) {
this.lockRes = res;
this.newCondition = newCondition;
}
@Override
public void run() {
while (true) {
try {
//此处,切勿重新new condition,因为生产者和消费者必须要用通一把锁资源,如果重新new的话,则不同了,所以此处需要注意
//Condition newCondition=lockRes.lock.newCondition();
lockRes.lock.lock();
if (!lockRes.flag) {
try {
newCondition.await();//线程等待
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(lockRes.userName + "," + lockRes.sex);
newCondition.signal();//唤醒
} catch (Exception e) {
e.printStackTrace();
} finally {
lockRes.lock.unlock();
}
}
}
}
public class LockThread {
public static void main(String[] args) {
LockRes res = new LockRes();
Condition condition = res.lock.newCondition();
//写的线程
LockOut out = new LockOut(res, condition);
//读的线程
LockInput input = new LockInput(res, condition);
out.start();
input.start();
}
}
特别注意点是newCondition.await();方法的使用,不能用成是wait方法。
Lock接口与synchroinzed关键字的区别
1、Lock接口可以尝试非阻塞的获取锁,当线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
2、Lock接口能被中断的获取锁,与synchronized不同,获取到的锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。
3、Lock接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。