Java多執行緒之生產者消費者問題:使用重入鎖、條件變數優雅地解決生產者消費者問題
阿新 • • 發佈:2019-01-10
Java5中新增了大量執行緒同步的功能,比如顯式Lock,讀寫鎖ReadWriteLock,條件變數Condition等,雖然這些功能使用之前的synchronized同步關鍵字都可能實現,但自己使用同步關鍵字不僅管理混亂,而且容易出錯。 如下是使用顯式Lock和條件變數Condition更好的解決生產者消費者問題,關於lock和condition讀者可以自己查閱相關說明,也很好理解。
Consumer.java
Creator.javapackage CreatorAndConsumer; public class Consumer implements Runnable { /** * 執行緒資源 */ private Plate plate; public Consumer(Plate plate) { this.plate = plate; } @Override public void run() { plate.getEgg(); } }
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>