011.多執行緒-lock鎖
阿新 • • 發佈:2018-12-27
類似於上一篇使用synchronized實現生產者與消費者間的通訊,
這裡使用lock鎖來實現。
package cn.qbz.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author: 花生米
* @Date: 2018/11/15 22:04
*/
public class LockTest {
public static void main(String[] args) {
Student student = new Student();
Lock lock = new ReentrantLock();
Condition produceCondition = lock.newCondition();
Condition consumerCondition = lock.newCondition();
ProduceTest produceTest = new ProduceTest(student, lock, produceCondition, consumerCondition);
ConsumerTest consumerTest = new ConsumerTest(student, lock, produceCondition, consumerCondition);
produceTest.start();
consumerTest.start();
}
}
class ProduceTest extends Thread {
private Student student;
private Lock lock;
private Condition produceCondition;
private Condition consumerCondition;
public ProduceTest(Student student, Lock lock,
Condition produceCondition,
Condition consumerCondition) {
this.student = student;
this.lock = lock;
this.produceCondition = produceCondition;
this.consumerCondition = consumerCondition;
}
@Override
public void run() {
int num = 1;
while (true) {
lock.lock();
try {
//如果可以生產,生產者生產
if (student.getCanProduce()) {
if (num == 1) {
student.setAge(6);
student.setName("小王");
num = 0;
} else {
student.setName("老王");
student.setAge(99);
num = 1;
}
//重置生產者不可以生產
student.setCanProduce(false);
}
consumerCondition.signalAll();
produceCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
class ConsumerTest extends Thread {
private Student student;
private Lock lock;
private Condition produceCondition;
private Condition consumerCondition;
public ConsumerTest(Student student, Lock lock, Condition produceCondition, Condition consumerCondition) {
this.student = student;
this.lock = lock;
this.produceCondition = produceCondition;
this.consumerCondition = consumerCondition;
}
@Override
public void run() {
while (true) {
lock.lock();
try {
//如果不可以生產,進行消費
if (!student.getCanProduce()) {
//重置生產者可以生產
student.setCanProduce(true);
System.out.println(student.toString());
}
produceCondition.signalAll();
consumerCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
class Student {
private String name;
private Integer age;
private Boolean canProduce = true;
public Boolean getCanProduce() {
return canProduce;
}
public void setCanProduce(Boolean canProduce) {
this.canProduce = canProduce;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
lock中常用方法:
lock()、unlock()
Lock lock = new ReentrantLock();
lock.lock();
try{
//可能會出現執行緒安全的操作
}finally{
//一定在finally中釋放鎖
//也不能把獲取鎖在try中進行,因為有可能在獲取鎖的時候丟擲異常
lock.unlock();
}
await()、signal()、signalAll()
Lock lock = new ReentrantLock();
Condition produceCondition = lock.newCondition();
Condition consumerCondition = lock.newCondition();
consumerCondition.signalAll();
produceCondition.await();
lock中的await方法類似於synchronized的wait,
signal、signalAll類似於notify、notifyAll。
需要注意:
雖然多個執行緒使用同一把lock鎖,
但是每個執行緒的condition都是唯一的,
使用時需要注意。
trylock()
其功能與 lock() 一樣,不過會有返回值,
true:獲取到lock鎖;false:未獲取lock鎖。
if (lock.tryLock()) {
try {
//如果不可以生產,進行消費
if (!student.getCanProduce()) {
//重置生產者可以生產
student.setCanProduce(true);
System.out.println(student.toString());
}
produceCondition.signalAll();
consumerCondition.await();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
tryLock(long time, TimeUnit unit)
與tryLock()類似,
只不過在未獲取到鎖時,設定了一個等待時間來嘗試再次拿鎖。