一、疑問
如果我們想執行具體喚醒哪個阻塞的線程,應該怎麼做?
在之前解決線程安全的過程中,雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,
但是我們並沒有直接看到在哪裏加上了鎖,在哪裏釋放了鎖,
爲了①更清晰的表達如何加鎖和釋放鎖 ②指定具體喚醒哪個線程
JDK5以後提供了一個新的鎖對象Lock。
使用Lock改寫生產者消費者問題(只改動了Resource類):
package com.thread.pcprob2;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 共享數據
* @author dqf
*
*/
public class Resource {
//產品編號
private Integer proNo = 0;
//判斷是消費數據,還是生產數據
private boolean flag = false;
Lock lock = new ReentrantLock();
//生產者阻塞
Condition condition1 = lock.newCondition();
//消費者阻塞
Condition condition2 = lock.newCondition();
//生產數據
public void produce(){
lock.lock();
try {
while(flag){//如果flag=true,則等待消費;
condition1.await();
}
System.out.println("生產-->" + (++proNo));
flag = true;
condition2.signal();
} catch (Exception e) {
}finally{
lock.unlock();
}
}
//消費數據
public void consume(){
lock.lock();
try {
while(!flag){//如果flag=false,則等待生產
condition2.await();
}
System.out.println("消費-------->" + proNo);
flag = false;
condition1.signal();
} catch (Exception e) {
// TODO: handle exception
}finally{
lock.unlock();
}
}
}
package com.thread.pcprob2;
/**
* 消費者
* @author dqf
*
*/
public class Consumer implements Runnable{
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
@Override
public void run() {
while(true){
res.consume();
}
}
}
package com.thread.pcprob2;
/**
* 生產者
* @author dqf
*
*/
public class Producer implements Runnable{
private Resource res;
public Producer(Resource res) {
this.res = res;
}
@Override
public void run() {
while(true){
res.produce();
}
}
}
package com.thread.pcprob2;
public class App {
public static void main(String[] args) {
Resource res = new Resource();
Producer p = new Producer(res);
Consumer c = new Consumer(res);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}