在MultiThreading中使用wait和notify方法

时间:2014-01-23 01:31:53

标签: java multithreading collections

现在,我开始研究线程并决定编写这个类来演示多线程的想法,但输出并不是我想要的。

我写的课程如下: -

import java.util.LinkedList;
class QueueTest extends LinkedList{
    int capacity;
    LinkedList list;
    public QueueTest(int capacity){
        this.capacity = capacity;
        list = new LinkedList();
    }
    public synchronized void addElements(int i)throws InterruptedException{
        if(list.size() == capacity ){
                wait();
        }
        add(i);
        System.out.println("I added : "+i);
        notify();
    }
    public synchronized int getElements() throws InterruptedException{
        if(!isEmpty()){
                wait();
        }
        int i = (Integer) list.remove();
        System.out.println("I got : "+i);
        notify();
        return i;
    }
}
class Add implements Runnable{
    QueueTest t ;
    public Add(QueueTest t){
        this.t = t;
        new Thread(this,"Add").start();
    }
    @Override
    public void run(){
        int i = 0;
        while(t.size() <= t.capacity){
            try{
                t.addElements(i++);} catch(InterruptedException e){}
        }
    }
}
class Remove implements Runnable{
    QueueTest t ;
    public Remove(QueueTest t){
        this.t = t;
        new Thread(this,"Remove").start();
    }
    @Override
    public void run(){
        while(!t.isEmpty()){
            try{
            t.getElements();} catch(InterruptedException e){}
        }
    }
}
public class FullQueue{
    public static void main(String[] args){
        QueueTest t = new QueueTest(5);
        new Add(t);
        new Remove(t);
    }
}

我希望输出就像那样

i added : 1
i got : 1
i added : 2
i got : 2 

......等等,但我得到了那个输出

I added : 0
I added : 1
I added : 2
I added : 3
I added : 4
I added : 5

2 个答案:

答案 0 :(得分:0)

因为两个线程同时运行,所以无论何时或以何种顺序运行都无法保证或控制。

get可以在set之前完全运行,set可以先完全运行,或者它们可以全部混合运行。

上面显示的偶数交错不太可能发生。

在这种情况下,列表已被一个线程完全填充,但是空线程首先运行并在它发现列表中没有任何内容时退出。

添加诊断程序以显示每个线程的开始和结束时间,您应该看到它。结果会随着每次运行而变化。

目前你的notify没有做任何事情,因为你没有等待。要使线程交替,然后在每次写入或读取后,您应该通知然后等待。你需要同步整个块,基本上你最终会得到一个非常复杂的方法来获得与一个线程运行相同的结果。

答案 1 :(得分:0)

这充满了竞争条件。请注意,如果没有元素,则Remove线程将立即退出。