首先创建生产者和消费者工厂类
Object lock = new Object();
boolean flag = false;
int count = 0;
/**
* 生产者
* @throws InterruptedException
*/
public void product() throws InterruptedException{
synchronized(lock){
if(!flag){
System.out.println("生产者生产的第"+count+"个");
flag = true;
lock.notify();
} else {
lock.wait();
}
}
}
/**
* 消费者
* @throws InterruptedException
*/
public void consume() throws InterruptedException{
synchronized(lock){
if(flag){
System.out.println("消费者消费的第"+count+"个");
count++;
flag = false;
lock.notify();
} else {
lock.wait();
}
}
}
创建 生产者和消费者的多线程类
private ThreadFactory threadFactory;
public ProductThread(ThreadFactory threadFactory) {
super();
this.threadFactory = threadFactory;
}
public void run(){
try {
while(true){
threadFactory.product();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private ThreadFactory threadFactory;
public ConsumeThread(ThreadFactory threadFactory) {
super();
this.threadFactory = threadFactory;
}
public void run(){
try {
while(true){
threadFactory.consume();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
测试类
public class Test {
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactory();
ProductThread productThread = new ProductThread(threadFactory);
productThread.start();
ConsumeThread consumeThread = new ConsumeThread(threadFactory);
consumeThread.start();
}
}
控制台的打印结果,可以发现每当生产者生成一个消费者消费一个。
如果有多个生产者和消费者呢?
改造代码
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactory();
ProductThread productThread = new ProductThread(threadFactory);
productThread.start();
ProductThread productThread1 = new ProductThread(threadFactory);
productThread1.start();
ConsumeThread consumeThread = new ConsumeThread(threadFactory);
consumeThread.start();
ConsumeThread consumeThread1 = new ConsumeThread(threadFactory);
consumeThread1.start();
}
打印结果
会发现生产者生产3后,线程没有执行了。这是为什么呢?看代码
当生产者生产完3后,将flag置为true,然后notify(),此时会唤醒一个线程,所以就会出现一个生产者和两个消费者竞争.当生产者获取的CPU使用权后,会进入product方法,但是由于flag= true,则直接进入lock.wait();所以我们希望当唤醒线程时,只唤醒消费者的线程。
Condition关键字
condition的介绍这里就不解释了,网上相关的知识特别多。简而言之就是它可以特定的唤醒线程,而不是像notify一样全部唤醒
condition需要借助Lock来实现,它的await(),signal(),signalAll()相当于wait(),notify(),notifyAll()。
public class ThreadFactory {
//Object lock = new Object();
boolean flag = false;
int count = 0;
Lock lock = new ReentrantLock();
Condition productCondition = lock.newCondition();
Condition consumeCondition = lock.newCondition();
/**
* 生产者
* @throws InterruptedException
*/
public void product() throws InterruptedException{
lock.lock();
try {
if(!flag){
System.out.println("生产者生产的第"+count+"个");
flag = true;
consumeCondition.signal();
} else {
productCondition.await();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* 消费者
* @throws InterruptedException
*/
public void consume() throws InterruptedException{
lock.lock();
try {
if(flag){
System.out.println("消费者消费的第"+count+"个");
count++;
flag = false;
productCondition.signal();
} else {
consumeCondition.await();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
这样一来,在生产者里面唤醒的是消费者,而在消费者里面唤醒生产者。