`
FindWG
  • 浏览: 7603 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

马士兵线程 消费者和生产者部分的错误

阅读更多

现在在学java基础,在看一些马士兵老师的视频,确实通俗易懂。

最近看到线程这一章时,发现运行 消费者和生产者 代码部分时,总会出现先消费生产。

源代码如下:

public class ProducerConsumer {
	public static void main(String[] args) {
		SyncStack ss = new SyncStack();
		Producer p = new Producer(ss);
		Consumer c = new Consumer(ss);
		new Thread(p).start();

		new Thread(c).start();
	}
}

class WoTou {
	int id; 
	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) {
		while(index == arrWT.length) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();		
		arrWT[index] = wt;
		index ++;
	}
	
	public synchronized WoTou pop() {
		while(index == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		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((int)(Math.random() * 200));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}

class Consumer implements Runnable {
	SyncStack ss = null;
	Consumer(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((int)(Math.random() * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}

 运行结果:

消费了: WoTou : 0

生产了:WoTou : 0

生产了:WoTou : 1

生产了:WoTou : 2

生产了:WoTou : 3

生产了:WoTou : 4

消费了: WoTou : 4

生产了:WoTou : 5

生产了:WoTou : 6

生产了:WoTou : 7

消费了: WoTou : 7

生产了:WoTou : 8

消费了: WoTou : 8

生产了:WoTou : 9

消费了: WoTou : 9

生产了:WoTou : 10

消费了: WoTou : 10

生产了:WoTou : 11

消费了: WoTou : 11

生产了:WoTou : 12

生产了:WoTou : 13

消费了: WoTou : 12

生产了:WoTou : 14

消费了: WoTou : 13

消费了: WoTou : 14

生产了:WoTou : 15

消费了: WoTou : 15

生产了:WoTou : 16

消费了: WoTou : 16

生产了:WoTou : 17

消费了: WoTou : 17

生产了:WoTou : 18

消费了: WoTou : 18

生产了:WoTou : 19

消费了: WoTou : 19

消费了: WoTou : 6

消费了: WoTou : 5

消费了: WoTou : 3

消费了: WoTou : 2

消费了: WoTou : 1

 

应该是线程出现问题,在push()方法结束后,要打印生产了第几个窝头时,另一线程执行了起来,导致消费在生产之前。

 

修改代码:把打印部分都放进push()和pop()方法内,同时pop()方法返回类型为void。

代码如下:

public class ProducerConsumer {
	public static void main(String[] args) {
		SyncStack ss = new SyncStack();
		Producer p = new Producer(ss);
		Consumer c = new Consumer(ss);
		new Thread(p).start();

		new Thread(c).start();
	}
}

class WoTou {
	int id; 
	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) {
		while(index == arrWT.length) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();		
		arrWT[index] = wt;
		index ++;
		System.out.println("生产了:" + wt);
	}
	
	public synchronized void pop() {
		while(index == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		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);
			
			try {
				Thread.sleep((int)(Math.random() * 200));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}

class Consumer implements Runnable {
	SyncStack ss = null;
	Consumer(SyncStack ss) {
		this.ss = ss;
	}
	
	public void run() {
		for(int i=0; i<20; i++) {
			ss.pop();
			
			try {
				Thread.sleep((int)(Math.random() * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics