如何正确创建SynchronizedStack类?

nba*_*lle 7 java multithreading synchronization

我在Java中创建了一个简单的同步Stack对象,仅用于培训目的.这是我做的:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的问题:

  • 可以不同步isEmtpy()方法吗?我认为这是因为即使另一个Thread同时修改堆栈,它仍然会返回一致的结果(没有进入isEmpty状态的操作既不是初始状态也不是最终状态).或者同步对象的所有方法是否同步是一种更好的设计?

  • 我不喜欢这种forcePop()方法.我只是想创建一个线程,它能够等到一个项目被推入堆栈之后再弹出一个元素,我认为最好的选择是用线程wait()run()方法做循环,但我不能因为它会抛出一个IllegalMonitorStatException.做这样的事情的正确方法是什么?

  • 还有其他意见/建议吗?

谢谢!

axt*_*avt 9

  • Stack本身已经同步,所以再次应用同步是没有意义的(ArrayDeque如果你想要一个非同步的堆栈实现,请使用它)

  • 这不好(除了前一点的事实),因为缺乏同步可能会导致内存可见性效果.

  • forcePop()非常好.虽然它应该通过InterruptedException而不是遵循可中断阻塞方法的合同.它允许你forcePop()通过调用来中断被阻塞的线程Thread.interrupt().