方法一:使用 synchronized + wait, notify实现。(一个生产者、一个消费者)
package pack2;
import java.util.ArrayList;
import java.util.Random;
public class PCTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ProductBox box = new ProductBox(5);
Producer producer = new Producer(box);
Consumer consumer = new Consumer(box);
Thread pt = new Thread(producer);
Thread ct = new Thread(consumer);
pt.start();
ct.start();
try {
pt.join();
ct.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ProductBox
{
public ProductBox(int num)
{
maxCapacity = num;
products = new int[num];
produceIndex = consumeIndex = productsNum = 0;
generator = new Random();
}
public synchronized void produce()
{
while(productsNum == maxCapacity)
{
try {
System.out.println("producer waiting now");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int tmp = generator.nextInt() % 100;
products[produceIndex] = tmp;
productsNum ++;
produceIndex = (produceIndex + 1) % maxCapacity;
System.out.println("producer thread " + Thread.currentThread().getName() + " produce a new product " + tmp +
", current index is " + produceIndex);
notify();
}
public synchronized void consume()
{
while(productsNum == 0)
{
try {
System.out.println("consumer waiting now");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int tmp = products[consumeIndex];
productsNum --;
consumeIndex = (consumeIndex + 1) % maxCapacity;
System.out.println("consumer thread " + Thread.currentThread().getName() + " consume a product " + tmp +
", current index is " + consumeIndex);
notify();
}
private int maxCapacity;
private int[] products;
private int produceIndex;
private int consumeIndex;
private int productsNum;
private Random generator;
}
class Producer implements Runnable
{
public Producer(ProductBox box)
{
productBox = box;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
for(int i = 0; i < 10; i ++)
{
productBox.produce();
Thread.sleep(10);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
private ProductBox productBox;
}
class Consumer implements Runnable
{
public Consumer(ProductBox box)
{
productBox = box;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
for(int i = 0; i < 10; i ++)
{
productBox.consume();
Thread.sleep(100);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
private ProductBox productBox;
}
方法二: ReetrantLock + await, signal, signalAll实现。( 多个生产者,多个消费者)
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PCTest2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ProductBox box = new ProductBox(5);
/* Producer producer = new Producer(box);
Consumer consumer = new Consumer(box);
Thread pt = new Thread(producer);
Thread ct = new Thread(consumer);*/
Thread pt[] = new Thread[3];
Thread ct[] = new Thread[3];
for(int i = 0; i < 3; i ++)
{
Producer producer = new Producer(box);
Consumer consumer = new Consumer(box);
pt[i] = new Thread(producer);
ct[i] = new Thread(consumer);
}
for(int i = 0; i < 3; i ++)
{
ct[i].start();
pt[i].start();
}
for(int i = 0; i < 3; i ++)
{
try {
pt[i].join();
ct[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Producer.countTotal();
Consumer.countTotal();
}
}
class ProductBox
{
public ProductBox(int num)
{
maxCapacity = num;
products = new int[num];
produceIndex = consumeIndex = productsNum = 0;
generator = new Random();
}
public void produce()
{
lock.lock();
try
{
while(productsNum == maxCapacity)
{
try {
System.out.println("producer " + Thread.currentThread().getName() + " waiting now");
condCanPoroduce.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int tmp = generator.nextInt() % 100;
products[produceIndex] = tmp;
productsNum ++;
produceIndex = (produceIndex + 1) % maxCapacity;
System.out.println("producer thread " + Thread.currentThread().getName() + " produce a new product " + tmp +
", current totalNum is " + productsNum);
condCanConsume.signalAll();
}
finally{
lock.unlock();
}
}
public void consume()
{
lock.lock();
try
{
while(productsNum == 0)
{
try {
System.out.println("consumer " + Thread.currentThread().getName() + " waiting now");
condCanConsume.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int tmp = products[consumeIndex];
productsNum --;
consumeIndex = (consumeIndex + 1) % maxCapacity;
System.out.println("consumer thread " + Thread.currentThread().getName() + " consume a product " + tmp +
", current totalnum is " + productsNum);
condCanPoroduce.signalAll();
}
finally{
lock.unlock();
}
}
private int maxCapacity;
private int[] products;
private int produceIndex;
private int consumeIndex;
private int productsNum;
private Random generator;
private final ReentrantLock lock = new ReentrantLock();
private final Condition condCanPoroduce = lock.newCondition();
private final Condition condCanConsume = lock.newCondition();
}
class Producer implements Runnable
{
public Producer(ProductBox box)
{
productBox = box;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
for(int i = 0; i < 30; i ++)
{
productBox.produce();
totalProducts ++;
Thread.sleep(100);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public static void countTotal()
{
System.out.println("Producers total produced products is " + totalProducts);
}
private ProductBox productBox;
private static int totalProducts = 0;
}
class Consumer implements Runnable
{
public Consumer(ProductBox box)
{
productBox = box;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
for(int i = 0; i < 30; i ++)
{
productBox.consume();
totalProducts ++;
Thread.sleep(100);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public static void countTotal()
{
System.out.println("Consumers total consumed products is " + totalProducts);
}
private ProductBox productBox;
private static int totalProducts = 0;
}