class TestProducerConsumer{
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{
WoTou[] arrWT = new WoTou[6];
int index = 0;

synchronized void push(WoTou wt){
while(index == arrWT.length){
try{
this.wait();
}
catch(InterruptedException e){
System.out.println(e);
}
}
this.notify();
arrWT[index] = wt;
index ++;
}

synchronized  WoTou pop(){
while(index == 0){
try{
this.wait();
}
catch(InterruptedException e){
System.out.println(e);
}
}
this.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<10; i++){
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
}
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<10; i++){
WoTou wt = ss.pop();
System.out.println("消费了:" + wt);
try{
Thread.sleep((int)(Math.random() * 1000));

catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
在Producer和Consumer中不加sleep的话为什么会出现不按顺序的取数,而加上的话就没事?

解决方案 »

  1.   

    因为处理机对各线程的调度是未知且不可预见的。
    你不加sleep的话,两个线程的调度顺序是不确定的,自然不会按顺序取数。
    加上sleep之后,每当其中一个线程(设生产线程)生产一次之后,会等待一段时间
    处理机会利用这个时间去调度另一个线程,另一个线程(消费线程)消费一次之后,也会等待一段时间
    如此反复,以保证你取出的数是你预想的顺序。
      

  2.   

    这两个线程相当于是并行的,而且执行内容都很少,时间都非常快,顺序自然不会固定。
    但有一点,
    这只跟生产的线程中的sleep有关系,跟消费中的sleep没关系,因为消费需要等生产出来之后可以可以消费,而相反,生产可以一直持续,而不需要等消费了之后才生产。
    可以把这两个线程中的sleep分别单独去掉,试一下就明白了。
      

  3.   

    这里直接用boolean判断 这是生产者消费者最容易的解决方法
      

  4.   

    两个start jvm 是随机执行的!