Java JDK1.5增加了一个新特性Lock和Conndition接口,Lock对象代替了synchronized同步代码,将同步代码快中的锁对象换成了Condition对象。
一个同步代码块只有一个锁对象对应,如果需要两个锁对象的话就需要再加一个同步代码块,这样就容易产生死锁。
使用了Lock和Condition的话,将锁对象的wait,notify和notifyAll替换成了Condition对象的await,signal。
这样就不需要使用多个同步代码块而且可以唤醒指定的线程。
以消费者和生产者为例来演示一下。两个生产者和两个消费者,实现交替运行,即生产一个商品就消费一个商品,不能出现连续生产两个商品或者连续消费两个商品:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Resources {
private static Resources mRes = null;
private String mName;
private boolean mFlag = false;
private int mNumber = 1;
private final ReentrantLock locker = new ReentrantLock();
private final Condition productCondition = locker.newCondition();
private final Condition consumerCondition = locker.newCondition();
private Resources() {
}
public static Resources getInstance() {
if (mRes == null) {
synchronized (Resources.class) {
if (mRes == null) {
mRes = new Resources();
}
}
}
return mRes;
}
public void set(String name) {
locker.lock();
try{
// 如果已经生成了一个商品,就等待消费者消费
while (mFlag) {
try {
productCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mName = name + "--" + mNumber++;
System.out.println(Thread.currentThread().getName() + "---------生成者: "
+ mName);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
mFlag = true;
consumerCondition.signal();;
}finally{
locker.unlock();
}
}
public void out() {
locker.lock();
try{
// 如果消费了商品后,就等待生产者生成
while (!mFlag) {
try {
consumerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "消费者: " + mName);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
mFlag = false;
productCondition.signal();
}finally{
locker.unlock();
}
}
}
class Product implements Runnable {
public void run() {
Resources res = Resources.getInstance();
while (true)
res.set("--------------商品----");
}
}
class Consumer implements Runnable {
public void run() {
Resources res = Resources.getInstance();
while (true)
res.out();
}
}
public class Main {
public static void main(String[] args) {
Product p = new Product();
Consumer c = new Consumer();
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
new Thread(c).start();
}
}