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接口在指定的截止時間之前獲取鎖,如果截止時間到了依舊無法獲取鎖,則返回。