Проблемы реализации BlockingQueue с нуля

Я пытаюсь построить свой собственный вариант BlockingQueue, основанный на найденном здесь.

public class ThreadSafeContainer<E> {
private Node front;
private Node end;
private int capacity;
private int size;

public ThreadSafeContainer(int capacity) {
    size = 0;
    this.capacity = capacity;
}

public synchronized void add(E item) {
    while (size == capacity) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    if (size == 0) {
        notifyAll();
    }

    Node tmp = new Node(item);

    if (end == null) {
        front = tmp;
        end = tmp;
    } else {
        end.next = tmp;
        end = end.next;
    }

    size++;
}

public synchronized E remove() {
    while (size == 0) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    if (size == capacity) {
        notifyAll();
    }

    E item = front.item;
    front = front.next;
    size--;
    return item;
}

private class Node {
    E item;
    Node next;

    public Node(E item) {
        this.item = item;
    }
}

Но по какой-то причине, когда я пытаюсь запустить потоки, как это

    Thread thread1 = new Thread() {
        public void run() {
            queue.add(1);
            queue.add(2);
        }
    };

    Thread thread2 = new Thread() {
        public void run() {
            System.out.println(queue.remove());
            System.out.println(queue.remove());
        }
    };      

Я получаю это исключение

Исключение в потоке "Thread-3" java.lang.NullPointerException в ThreadSafeContainer.remove(ThreadSafeContainer.java:52) в ThreadPractice$2.run(ThreadPractice.java:17) в java.lang.Thread.run(неизвестный источник)

Я могу удалить ошибку, изменив размер == 0 на front == null, но он все равно не выдает то же самое.

1 ответ

В настоящее время, если вызов remove() когда-либо удаляет последний элемент, вы в конечном итоге front == null но end == //the last created node, Что означает следующий звонок add будет только обновлять endне frontи соответствующий вызов remove() бросит ваш NPE.

Вы можете проверить front == null в конце remove()или измените тест в add от end == null в size == 0 или же front == null,

Кроме того, если вы публикуете трассировку стека, полезно добавить комментарий, указывающий, какая строка в вашем фрагменте соответствует номерам строк в исключении.

Другие вопросы по тегам