Java 如何正确创建SynchronizedStack类?
我用Java制作了一个简单的同步堆栈对象,只是为了进行培训。 以下是我所做的:Java 如何正确创建SynchronizedStack类?,java,multithreading,synchronization,Java,Multithreading,Synchronization,我用Java制作了一个简单的同步堆栈对象,只是为了进行培训。 以下是我所做的: public class SynchronizedStack { private ArrayDeque<Integer> stack; public SynchronizedStack(){ this.stack = new ArrayDeque<Integer>(); } public synchronized Integer p
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;
}
}
公共类SynchronizedStack{
专用ArrayDeque堆栈;
公共同步堆栈(){
this.stack=new ArrayDeque();
}
公共同步整数pop(){
返回这个.stack.pop();
}
public-synchronized int-forcePop(){
while(isEmpty()){
System.out.println(“堆栈为空”);
试一试{
等待();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
返回这个.stack.pop();
}
公共同步无效推送(int i){
这个.栈.推(i);
notifyAll();
}
公共布尔值为空(){
返回此.stack.isEmpty();
}
公共同步void pushAll(int[]d){
对于(int i=0;i
以下是我的问题:
- 不同步
方法可以吗?我认为这是因为即使另一个线程同时修改堆栈,它仍然会返回一致的结果(没有任何操作进入非初始或最终的等空状态)。或者让同步对象的所有方法都同步是更好的设计isEmtpy()
- 我不喜欢
方法。我只是想创建一个线程,在弹出一个元素之前可以等到一个项目被推入堆栈,我认为最好的选择是使用线程的forcePop()
方法中的run()
进行循环,但我不能,因为它抛出了一个wait()
。这样做的正确方法是什么illegalMonitorStateException
- 还有其他意见/建议吗
谢谢大家! 不同步的唯一问题是不知道下面发生了什么。虽然您的推理是合理的,但它假定底层的
堆栈
也以合理的方式运行。在这种情况下很可能是这样,但一般来说你不能依赖它
问题的第二部分,阻塞pop操作没有错,请参阅所有可能策略的完整实现
还有一个建议:如果您创建的类可能会在应用程序的多个部分(甚至多个应用程序)中重复使用,请不要使用synchronized
方法。改为这样做:
public class Whatever {
private Object lock = new Object();
public void doSomething() {
synchronized( lock ) {
...
}
}
}
原因是您不知道类的用户是否希望在
实例上同步。如果这样做,它们可能会干扰类本身的操作。这样,您就拥有了自己的私有锁,没有人可以干预。假设stack.isEmpty()
不需要同步可能是真的,但您依赖于您无法控制的类的实现细节。
堆栈的javadocs声明该类不是线程安全的,因此您应该同步所有访问。
Stack
本身已经同步,因此再次应用同步是没有意义的(如果需要非同步的Stack实现,请使用ArrayDeque
)
- 这是不正常的(除了上一点之外),因为缺少同步可能会导致内存可见性影响
forcePop()
相当不错。虽然它应该通过InterruptedException
而不捕获它,以遵循可中断阻塞方法的契约。它允许您通过调用thread.interrupt()
来中断在forcePop()调用中阻塞的线程
我觉得你把习语混在一起了。您正在使用
java.util.Stack
支持您的SynchronizedStack
,而java.util.Vector
又支持synchronized
。我认为应该将wait()
和notify()
行为封装在另一个类中。不要锁定方法,而是锁定对象。阅读以下内容:堆栈扩展向量,该向量已同步。Don Roby:是的,正如axtavt所指出的,我现在使用的是ArrayDeque。Sean Patrick Floyd:所以你说这样做更好:public void pop(){synchronized(this.stack){return this.stack.pop();}}而不是public void synchronized pop(){return this.stack.pop();}?假设我在不依赖Stack/ArrayQue实现的情况下编写了此代码,但仅以我确信不存在可能导致不一致isEmpty()结果的传递状态的方式使用数组。最好不要同步它(更快)还是同步它(更安全)?无论如何同步它-问题是,如果没有一些同步,您可能-永远不会-在isEmpty()调用中看到来自另一个线程的更新。