Java5中新增了大量線程同步的功能,比如顯式Lock,讀寫鎖ReadWriteLock,條件變量Condition等,雖然這些功能使用之前的synchronized同步關鍵字都可能實現,但自己使用同步關鍵字不僅管理混亂,而且容易出錯。 如下是使用顯式Lock和條件變量Condition更好的解決生產者消費者問題,關於lock和condition讀者可以自己查閱相關說明,也很好理解。
Consumer.java
package CreatorAndConsumer;
public class Consumer implements Runnable {
/**
* 線程資源
*/
private Plate plate;
public Consumer(Plate plate) {
this.plate = plate;
}
@Override
public void run() {
plate.getEgg();
}
}
Creator.java
package CreatorAndConsumer;
/**
* 生產者
*
* @author Martin
*/
public class Creator implements Runnable {
/**
* 線程資源
*/
private Plate plate;
public Creator(Plate plate) {
this.plate = plate;
}
@Override
public void run() {
Object egg = new Object();
plate.addEgg(egg);
}
}
Plate.java
package CreatorAndConsumer;
import java.util.List;
import java.util.concurrent.locks.*;
/**
* 盤子,表示共享的資源
*
* @author Martin
*/
public class Plate {
private List<Object> eggs = new ArrayList<Object>();
/**
* 鎖
*/
private Lock lock;
/**
* 大於0條件變量,用於保證消費時有資源可消費
*/
private Condition more0Condition;
public Plate() {
lock = new ReentrantLock();
more0Condition = lock.newCondition();
}
/**
* 獲取蛋
*
* @return
*/
public Object getEgg() {
lock.lock();
try {
while (eggs.size() < 1) {
more0Condition.await();
}
System.out.println("消費者取蛋,當前剩餘:" + eggs.size());
Object egg = eggs.get(0);
eggs.remove(0);
return egg;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return null;
}
/**
* 加入蛋
*
* @return
*/
public void addEgg(Object egg) {
lock.lock();
System.out.println("生產者生蛋,當前剩餘:" + eggs.size());
eggs.add(egg);
more0Condition.signalAll();
lock.unlock();
}
}
Tester.java
package CreatorAndConsumer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Tester {
public static void main(String[] args)
{
//共享資源
Plate plate = new Plate();
ExecutorService pool = Executors.newFixedThreadPool(100);
//添加生產者和消費者
for(int i = 0 ; i < 1000; i ++)
{
pool.execute(new Creator(plate));
pool.execute(new Consumer(plate));
}
pool.shutdown();
}
}
</pre><pre>