Curious
Curious

Reputation: 921

Threading ArrayIndexOutofBoundException

I created a stack class like this. Some times it runs and sometimes it will through ArrayIndexOutofBoundException. What's wrong in threading? Couldn't understand please help.

public class StackImpl<E> implements Stack<E>{

private E[] stackArray;

private int topOfStack;

public StackImpl(int size) {
    stackArray = (E[]) new Object[size];
    topOfStack = -1;
}

public synchronized void push(E e) {
    while (isFull()) {
        try {
            System.out.println("stack is full cannot add " + e);
            wait();
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }
    }
    stackArray[++topOfStack] = e;
    System.out
            .println(Thread.currentThread() + " :notifying after pushing");
    notify();
}

public boolean isEmpty() {
    return topOfStack == 0;
}

public synchronized E pop() {
    while (isEmpty()) {
        try {
            System.out.println("stack is empty cannot pop ");
            wait();
        } catch (InterruptedException e) {

        }
    }
    System.out.println(topOfStack);
    E element = stackArray[topOfStack];
    stackArray[topOfStack--] = null;
    System.out.println(Thread.currentThread() + " notifying after popping");
    notify();
    return element;
}

public boolean isFull() {
    return topOfStack >= stackArray.length-1;
}

public static void main(String[] args) {
    final Stack<Integer> stack = new StackImpl<Integer>(10);
    (new Thread("Pusher") {
        public void run() {
            while (true) {
                stack.push(10);
            }
        }
    }).start();
    (new Thread("Popper") {
        public void run() {
            while (true) {
                stack.pop();
            }
        }
    }).start();
}

}

Upvotes: 0

Views: 136

Answers (1)

esaj
esaj

Reputation: 16035

You set

topOfStack = -1;

in the constructor of StackImpl, yet your isEmpty method checks for 0:

public boolean isEmpty() {
    return topOfStack == 0;
}

So the while loop will fall through on first pop, if the pusher hasn't added any values yet:

    public synchronized E pop() {
        while (isEmpty()) {
            try {
                System.out.println("stack is empty cannot pop ");
                wait();
            } catch (InterruptedException e) {

            }
        }

Set the topOfStack to 0 on the constructor and it should work.

Edit: come to think of it, instead change the isEmpty -method to return topOfStack < 0;, and leave the topOfStack = -1; in your constructor... otherwise element in index 0 is never popped.

Upvotes: 5

Related Questions