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();
}
}