---------------------- android培训、java培训、期待与您交流! ----------------------
生产者消费者问题:
生产者生产一个商品消费者消费一个商品。有多个线程在生产和消费。
public class ProduceConsumerDemo {
public static void main(String[] args) {
Resource res = new Resource();
Produce pro = new Produce(res);
Consumer con = new Consumer(res);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
//Thread t3 = new Thread(pro);
//Thread t4 = new Thread(con);
t1.start();
t2.start();
//t3.start();
//t4.start();
}
}
class Resource {
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void entey(String name) {
if (flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
count++;
System.out.println(Thread.currentThread().getName() + "-->生产"
+ this.name+count);
flag = true;
this.notify();
}
public synchronized void out() {
if (!flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "------>消费"
+ this.name+this.count);
flag = false;
this.notify();
}
}
class Produce implements Runnable {
private Resource res;
public Produce(Resource res) {
this.res = res;
}
public void run() {
while(true){
res.entey("商品");
}
}
}
class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
public void run() {
while(true)
res.out();
}
}
该问题中生产者和消费者各有一个,两个线程运行。结果是成产一个消费一个。
但是启动多个线程,就会出现问题,同一个生产多次,只消费一次的错误。
原因:当一个线程在wait时 另一个线程进入改变了数据,当该线程醒来时不再判断flag标记,然后直接生产,出现两个线程生产同一个商品。
解决方法是使用while循环,并且使用notifyAll 来解决。
修改后的代码如下:
public class ProduceConsumerDemo {
public static void main(String[] args) {
Resource res = new Resource();
Produce pro = new Produce(res);
Consumer con = new Consumer(res);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource {
private String name;
private int count;
private boolean flag = false;
public synchronized void entey(String name) {
while (flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
count++;
System.out.println(Thread.currentThread().getName() + "-->生产"
+ this.name+count);
flag = true;
this.notifyAll();
}
public synchronized void out() {
while (!flag)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "------>消费"
+ this.name+this.count);
flag = false;
this.notifyAll();
}
}
class Produce implements Runnable {
private Resource res;
public Produce(Resource res) {
this.res = res;
}
public void run() {
while(true){
res.entey("商品");
}
}
}
class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
public void run() {
while(true)
res.out();
}
}
Jdk5.0中提供了多线程的解决方法-->显示的所机制和等待唤醒机制
将同步synchronized操作替换为Lock操作。
将Object对象中的wait notify notifyAll 替换为Condition 对象。
利用condition 对象可以获取锁,唤醒锁。
import java.util.concurrent.locks.*;
public class ProduceConsumerDemo {
public static void main(String[] args) {
Resource res = new Resource();
Produce pro = new Produce(res);
Consumer con = new Consumer(res);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource {
private String name;
private int count;
private boolean flag = false;
//一个锁对应多个condition对象
final Lock lock = new ReentrantLock();
final Condition con1 = lock.newCondition();
final Condition con2 = lock.newCondition();
public void enter(String name) {
lock.lock();
try {
while (flag)
con1.await();// await会抛异常
this.name = name;
count++;
System.out.println(Thread.currentThread().getName() + "-->生产"
+ this.name + count);
flag = true;
con2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while (!flag)
con2.await();
System.out.println(Thread.currentThread().getName() + "------>消费"
+ this.name + this.count);
flag = false;
con1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
class Produce implements Runnable {
private Resource res;
public Produce(Resource res) {
this.res = res;
}
public void run() {
while (true) {
res.enter("商品");
}
}
}
class Consumer implements Runnable {
private Resource res;
public Consumer(Resource res) {
this.res = res;
}
public void run() {
while (true)
res.out();
}
}
在该示例中生产者的condition对象只唤醒消费者等待的线程。
如:
con1.await();.......con1.signal();
Con2.await();.......con2.signal();