Как правильно создать класс SynchronizedStack?
Я сделал простой синхронизированный объект стека в Java, только для учебных целей. Вот что я сделал:--7-->
public class SynchronizedStack {
    private ArrayDeque<Integer> stack;
    public SynchronizedStack(){
        this.stack = new ArrayDeque<Integer>();     
    }
    public synchronized Integer pop(){
        return this.stack.pop();
    }
    public synchronized int forcePop(){
        while(isEmpty()){
            System.out.println("    Stack is empty");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return this.stack.pop();
    }
    public synchronized void push(int i){
        this.stack.push(i);
        notifyAll();
    }
    public boolean isEmpty(){
        return this.stack.isEmpty();
    }
    public synchronized void pushAll(int[] d){
        for(int i = 0; i < d.length; i++){
            this.stack.push(i);
        }
        notifyAll();
    }
    public synchronized String toString(){
        String s = "[";
        Iterator<Integer> it = this.stack.iterator();   
        while(it.hasNext()){
            s += it.next() + ", ";
        }
        s += "]";
        return s;
    }
}
вот мои вопросы:
- это нормально, чтобы не синхронизировать - isEmtpy()способ? Я решил, что это потому, что даже если другой поток одновременно изменяет стек, он все равно вернет когерентный результат (нет операции, которая переходит в состояние isEmpty, которое не является ни начальным, ни окончательным). Или это лучше иметь все методы синхронизированного объекта синхронизированы?
- мне не нравится - forcePop()метод. Я просто хотел создать поток, который мог подождать, пока элемент не будет помещен в стек, прежде чем всплывать элемент, и я подумал, что лучший вариант-сделать цикл с- wait()на- run()метод потока, но я не могу, потому что выдает- IllegalMonitorStatException. Каков правильный метод, чтобы сделать что-то подобное?
- любой другой комментарий / предложение? 
спасибо!
4 ответов
- Stackсам уже синхронизирован, поэтому нет смысла снова применять синхронизацию (используйте- ArrayDequeЕсли вы хотите несинхронизированную реализацию стека)
- это не нормально (помимо факта с предыдущей точки), потому что отсутствие синхронизации может вызвать эффекты видимости памяти. 
- forcePop()- это очень хорошо. Хотя это должно пройти- InterruptedExceptionбез ловить его для следования контракта прерываемый метод блокировки. Это позволит вам прервать поток, заблокированный в- forcePop()звонок по телефону- Thread.interrupt().
предполагая, что stack.isEmpty() синхронизация может не потребоваться, но вы полагаетесь на детали реализации класса, над которым у вас нет контроля.
На javadocs государственной стек, что класс не является потокобезопасным, поэтому вы должны синхронизировать доступ.
Я думаю, вы немного смешиваете идиомы.  Вы поддерживаете свой SynchronizedStack с java.util.Stack, который, в свою очередь, опирается на java.util.Vector, которая составляет synchronized.  Я думаю, вы должны инкапсулировать wait() и notify() behaivor в другом классе.
единственная проблема с не синхронизация isEmpty() это то, что вы не знаете, что происходит внизу. Хотя ваше рассуждение, ну, разумно, оно предполагает, что лежащее в основе Stack также ведет себя разумно. Что, наверное, в этом случае, но вы не можете полагаться на него в целом.
и вторая часть вашего вопроса, нет ничего плохого в блокировке операции pop, см. этой для полной реализации всех возможных стратегия.
и еще одно предложение: если вы создаете класс, который, вероятно, будет повторно использоваться в нескольких частях приложения (или даже в нескольких приложениях), не используйте synchronized методы. Вместо этого:
public class Whatever {
  private Object lock = new Object();
  public void doSomething() {
    synchronized( lock ) {
      ...
    }
  }
}
причина этого в том, что вы действительно не знаете, хотят ли пользователи вашего класса синхронизировать на вашем Whatever случаях или нет. Если они это сделают, они могут помешать работе самого класса. Таким образом, у тебя будет свой собственный замок. которых никто не может помешать.
