一、疑问
如果我们想执行具体唤醒哪个阻塞的线程,应该怎么做?
在之前解决线程安全的过程中,虽然我们可以理解同步代码块和同步方法的锁对象问题,
但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,
为了①更清晰的表达如何加锁和释放锁 ②指定具体唤醒哪个线程
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();
}
}