版權聲明:本文爲博主原創文章,允許轉載,請標明出處。
類似於上一篇使用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()類似, 只不過在未獲取到鎖時,設置了一個等待時間來嘗試再次拿鎖。