public class TestProducerConsumer {
public static void main(String[] args) {
// TODO Auto-generated method stub
SyncStack ss=new SyncStack();
producer p=new producer(ss);
customer c=new customer(ss);
new Thread(p).start();
new Thread(c).start();
}
}class WoTou{
int id=0;
WoTou(int id){
this.id=id;
}
public String toString(){
return "WoTou"+id;
}
}class SyncStack{
int index=0;
WoTou [] ArrWT=new WoTou[6];
public synchronized void push(WoTou wt){
if(index>=ArrWT.length){
try{
System.out.println("满了,等待消费");
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
notify();
ArrWT[index]=wt;
index++;
}
public synchronized WoTou pop(){
if(index==0){
try{
System.out.println("没WoTou了,等待生产");
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
notify();
index--;
return ArrWT[index];
}
}class producer implements Runnable{
SyncStack ss=null;
producer(SyncStack ss){
this.ss=ss;
}
public void run(){
for (int i =0;i<20;i++){
WoTou wt=new WoTou(i);
ss.push(wt);
System.out.println("生产了:"+wt);
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
}class customer implements Runnable{
SyncStack ss=null;
customer(SyncStack ss){
this.ss=ss;
}
public void run(){
for(int i=0;i<20;i++){
WoTou wt=ss.pop();
System.out.println("消费了: "+wt);
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
得出的结果为:
生产了:WoTou0
消费了: WoTou0
生产了:WoTou1
生产了:WoTou2
生产了:WoTou3
生产了:WoTou4
消费了: WoTou4
生产了:WoTou5
生产了:WoTou6
生产了:WoTou7
满了,等待消费
生产了:WoTou8
消费了: WoTou7
满了,等待消费
消费了: WoTou8
生产了:WoTou9
满了,等待消费
生产了:WoTou10
消费了: WoTou9
满了,等待消费
生产了:WoTou11
消费了: WoTou10
满了,等待消费
消费了: WoTou11
生产了:WoTou12
满了,等待消费
生产了:WoTou13
消费了: WoTou12
满了,等待消费
生产了:WoTou14
消费了: WoTou13
满了,等待消费
消费了: WoTou14
生产了:WoTou15
满了,等待消费
生产了:WoTou16
消费了: WoTou15
满了,等待消费
生产了:WoTou17
消费了: WoTou16
满了,等待消费
消费了: WoTou17
生产了:WoTou18
满了,等待消费
生产了:WoTou19
消费了: WoTou18
消费了: WoTou19
消费了: WoTou6
消费了: WoTou5
消费了: WoTou3
消费了: WoTou2
消费了: WoTou1
提示满了,怎么还在生产呢?难道是wait()没起作用?请教高手。
public static void main(String[] args) {
// TODO Auto-generated method stub
SyncStack ss=new SyncStack();
producer p=new producer(ss);
customer c=new customer(ss);
new Thread(p).start();
new Thread(c).start();
}
}class WoTou{
int id=0;
WoTou(int id){
this.id=id;
}
public String toString(){
return "WoTou"+id;
}
}class SyncStack{
int index=0;
WoTou [] ArrWT=new WoTou[6];
public synchronized void push(WoTou wt){
if(index>=ArrWT.length){
try{
System.out.println("满了,等待消费");
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
notify();
ArrWT[index]=wt;
index++;
}
public synchronized WoTou pop(){
if(index==0){
try{
System.out.println("没WoTou了,等待生产");
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
notify();
index--;
return ArrWT[index];
}
}class producer implements Runnable{
SyncStack ss=null;
producer(SyncStack ss){
this.ss=ss;
}
public void run(){
for (int i =0;i<20;i++){
WoTou wt=new WoTou(i);
ss.push(wt);
System.out.println("生产了:"+wt);
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
}class customer implements Runnable{
SyncStack ss=null;
customer(SyncStack ss){
this.ss=ss;
}
public void run(){
for(int i=0;i<20;i++){
WoTou wt=ss.pop();
System.out.println("消费了: "+wt);
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
得出的结果为:
生产了:WoTou0
消费了: WoTou0
生产了:WoTou1
生产了:WoTou2
生产了:WoTou3
生产了:WoTou4
消费了: WoTou4
生产了:WoTou5
生产了:WoTou6
生产了:WoTou7
满了,等待消费
生产了:WoTou8
消费了: WoTou7
满了,等待消费
消费了: WoTou8
生产了:WoTou9
满了,等待消费
生产了:WoTou10
消费了: WoTou9
满了,等待消费
生产了:WoTou11
消费了: WoTou10
满了,等待消费
消费了: WoTou11
生产了:WoTou12
满了,等待消费
生产了:WoTou13
消费了: WoTou12
满了,等待消费
生产了:WoTou14
消费了: WoTou13
满了,等待消费
消费了: WoTou14
生产了:WoTou15
满了,等待消费
生产了:WoTou16
消费了: WoTou15
满了,等待消费
生产了:WoTou17
消费了: WoTou16
满了,等待消费
消费了: WoTou17
生产了:WoTou18
满了,等待消费
生产了:WoTou19
消费了: WoTou18
消费了: WoTou19
消费了: WoTou6
消费了: WoTou5
消费了: WoTou3
消费了: WoTou2
消费了: WoTou1
提示满了,怎么还在生产呢?难道是wait()没起作用?请教高手。
if (index >= ArrWT.length) {
try {
System.out.println("满了,等待消费");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ArrWT[index++] = wt;
System.out.println("生产了:" + wt);
notify();
} public synchronized WoTou pop() {
if (index == 0) {
try {
System.out.println("没WoTou了,等待生产");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费了: " + ArrWT[--index]);
notify();
return ArrWT[index];
}
if (index >= ArrWT.length) {
try {
System.out.println("满了,等待消费");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ArrWT[index++] = wt;
System.out.println("生产了:" + wt);
notify();
} public synchronized WoTou pop() {
if (index == 0) {
try {
System.out.println("没WoTou了,等待生产");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费了: " + ArrWT[--index]);
notify();
return ArrWT[index];
}
等到消费了,它的数量就少于6个了。然后它就又生产。直到生产producer类里规定的数量(20)为止.
生产了:WoTou7
满了,等待消费
生产了:WoTou8
消费了: WoTou7
notify();
index--; :这可以导致去生产!
return ArrWT[index];
当执行完这三句代码后,退出了方法,就说明c释放了对象的锁:p线程已经醒来,就会和c线程抢占资源,
此时customer中的
System.out.println("消费了: "+wt); 代码还没有执行。
这个时候就要看p和c线程那个能抢到资源了。
出现你这种情况是p抢占到了资源了,因为允许生产,所以就生产了。
然后p生产满了,然后c线程接着执行它的代码,所以你会看到这样的情况。
修改了一下lz的代码,lz好好揣摩一下!
public class TestProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
producer p = new producer(ss);
customer c = new customer(ss);
new Thread(p).start();
new Thread(c).start();
}
}class WoTou {
int id = 0; WoTou(int id) {
this.id = id;
} public String toString() {
return "WoTou" + id;
}
}class SyncStack {
int index = 0; WoTou[] ArrWT = new WoTou[6]; public synchronized void push(WoTou wt) {
if (index >= ArrWT.length) {
try {
System.out.println("---------------满了,等待消费");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
} }
ArrWT[index] = wt;
index++;
notify();//执行完自己的代码才去唤醒别人,要不别人就会和你抢cpu资源。 } // 改变这无返回值
public synchronized void pop() {
if (index == 0) {
try {
System.out.println("没WoTou了,等待生产");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();//虽然我唤醒了那些等待的线程,但线程我还是持有对象的锁!!!
index--;
// return ArrWT[index];
// 改变如下:
System.out.println("消费了: " + ArrWT[index]);
}
}class producer implements Runnable {
SyncStack ss = null; producer(SyncStack ss) {
this.ss = ss;
} public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
}}class customer implements Runnable {
SyncStack ss = null; customer(SyncStack ss) {
this.ss = ss;
} public void run() {
for (int i = 0; i < 20; i++) {
// WoTou wt=ss.pop();//锁定了对象
//执行到下面这句,你已经没有对象的锁!!!
// System.out.println("消费了: "+wt);
// 改变如下:
ss.pop();//锁定了对象
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
} }}关键还是持有对象的锁!!!
1.为什么满了还生产 :输出语句应该放在方法锁内,事实上已经消费了一个,但是由于输出语句在外面所以少打印一个
2.还有就是if (index >= ArrWT.length) {
改为while(index >= ArrWT.length) ----避免出现异常时还能再次判断
LZ参考下:/**
* 生产者消费者问题
*/
package net.csdn.blog.johnston;/**
* @author johnston678
*
* @version 2009-05-06
*/
public class ProducerConsumer { /**
* @param args
*/
public static void main(String[] args) {
ProductBox pb = new ProductBox();
Producer p = new Producer(pb);
Consumer c = new Consumer(pb);
Thread pThread = new Thread(p);
Thread cThread = new Thread(c);
pThread.setPriority(Thread.MAX_PRIORITY);
pThread.start();
cThread.start();
}}/**
* 产品对象
* @author johsnton678
*/
class Product {
int id; public Product(int id) {
super();
this.id = id;
}
public String toString(){
return "Product:" + id;
}
}/**
* 产品盒对象
* @author johnston678
*/
class ProductBox { Product[] productbox = new Product[6];
int index = 0;
public ProductBox() {
super();
}
public synchronized void push(Product p) {
while (index == productbox.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
productbox[index] = p;
index ++;
}
public synchronized Product pop() {
while (index == 0) {
try {
this.wait();
} catch (InterruptedException e) { e.printStackTrace();
}
}
this.notify();
index --;
return productbox[index];
}
}/**
* 生产者
* @author johnston678
*/
class Producer implements Runnable { ProductBox productbox = null;
public Producer(ProductBox productbox) {
super();
this.productbox = productbox;
} @Override
public void run() {
for (int i=0; i<10; i++) {
Product p = new Product(i);
productbox.push(p);
System.out.println("produce:" + p);
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}/**
* 消费者
* @author johnston678
*/
class Consumer implements Runnable { ProductBox productbox = null;
public Consumer(ProductBox productbox) {
super();
this.productbox = productbox;
} @Override
public void run() {
for (int i=0; i<10; i++) {
Product p = productbox.pop();
System.out.println("consume:" + p);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
produce:Product:0
consume:Product:0
produce:Product:1
produce:Product:2
produce:Product:3
produce:Product:4
produce:Product:5
produce:Product:6
consume:Product:6
produce:Product:7
consume:Product:7
produce:Product:8
consume:Product:8
produce:Product:9
consume:Product:9
consume:Product:5
consume:Product:4
consume:Product:3
consume:Product:2
consume:Product:1
思路是:一生产者一消费者一罐子
重点是罐子:
有两个同步方法取和存,取的时候发现没有可取就调用wait()阻塞(此时阻塞的是调用取方法的消费者线程)
存的时候发现罐子中的东西已经足够多,就调用wait()阻塞(此时阻塞的是调用存方法的生产者线程)
如果上述情况没有发生,则执行存和取,并在方法结束和return前调用notifyAll(),使所有阻塞线程重新转为竞争上岗状态。
调用wait()和notifyAll()方法时必须在当前线程上,否则会抛出一个运行时异常。
楼主的错误应该与线程无关,估计是判断环节出了漏子
已作出了分析,synchronized 用的this作为锁对象,同一时候也只有一个线程能拿到锁,wait(),notify()都不是长占锁操作,所以当你在pop()中notify()即叫醒了其它线程,
那么当pop()运行完了,锁交出,push()运行的线程可能会抢到锁开始运行,那么在消费者里的System.out.println("消费了: " + wt);就不会输出了......不过生产者消费者模式使用已在jdk1.5的时候已提供了很好的支持LinkedBlockingQueue
import java.util.ArrayList;
import java.util.Random;public class ThreadExercise {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
producer p = new producer(ss);
customer c = new customer(ss);
new Thread(p).start();
new Thread(c).start();
}
}class SyncStack {
int index = 0;
ArrayList[] al = new ArrayList[10]; public synchronized void push() {
//如果生产池满,就阻塞push
if (index >= al.length) {
try {
System.out.println("********生产池满,等待消费********");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//生产池不满,物品个数加1
index++;
System.out.println("生产1个物品" + " 生产池中有 " + index + "个物品");
}
notifyAll();// 唤醒等待的线程!
} public synchronized void pop() {
//如果生产池空,就阻塞pop
if (index == 0) {
try {
System.out.println("********生产池空,等待生产********");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//生产池不空,物品个数减1
index--;
System.out.println("消费1个物品 " + " 生产池中有 " + index + "个物品");
}
notifyAll();// 唤醒等待的线程!
}
}class producer implements Runnable {
SyncStack ss = null;
Random random = new Random(); producer(SyncStack ss) {
this.ss = ss;
} public void run() {
while (true) {
ss.push(); //生产物品
try {
Thread.sleep(random.nextInt(2000));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}class customer implements Runnable {
SyncStack ss = null;
Random random = new Random(); customer(SyncStack ss) {
this.ss = ss;
} public void run() {
while (true) {
ss.pop(); //消费物品
try {
Thread.sleep(random.nextInt(2000));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}