java - 定义线程安全类的两种方式的区别

标签 java multithreading collections synchronization

我想知道下面两个示例类有什么功能差异。哪种风格应该优于另一种风格以及原因。

public class MyQueue {
    private Queue<Abc> q;

    public MyQueue() {
        q = Collections.synchronizedList(new LinkedList<Abc>());
    }

    public void put(Abc obj) {
        q.add(obj);
    }

    public Abc get() {
        return q.remove();
    }
}

或者

public class MyQueue {
    private Queue<Abc> q;

    public MyQueue() {
        q = new LinkedList<Abc>();
    }

    public synchronized void put(Abc obj) {
        q.add(obj);
    }

    public synchronized Abc get() {
        return q.remove();
    }
}

我的看法是 - 就类中的这么多功能而言,两者都可以完美地工作,只是个人喜好问题。

如果有更多差异,请告诉我。

最佳答案

主要的架构差异是第二个实现将同步监视器(对象本身)暴露给外界。这意味着每个人都可能获取您用于内部同步的相同锁:

MyQueue myQueue = new MyQueue();  // a shared instance

synchronized(myQueue) {
    // No one else can call synchronized methods while you're here
}

它可能会带来好处或导致问题,具体取决于您的类用例。

第一个实现隐藏了同步的细节,这一事实为您在将来添加新功能提供了更大的灵 active (例如,您可以在 put() 中添加一些未同步的代码和 get() 方法(如果需要的话)),但会带来一个小问题,那就是在列表周围有一个额外的层。

否则,所提供的功能没有任何区别。

PS:不要忘记将 final 添加到 q 声明中。否则你的类不能保证所谓的安全发布并且不能被称为完全线程安全。

关于java - 定义线程安全类的两种方式的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39263746/

相关文章:

java - 创建指定参数类型或其子类型的 Arraylist

java - 在同一个类的另一个方法中调用一个方法

java - 服务器端的 webSockets 连接管理

java - 使用 Collection 框架计算值(value)的百分比

java - Fast-fail - 异常仅在添加元素时发生,而不是在删除时发生

java - 使用多个 onclicklistener 添加到 SharedPreference 值

java - 创建 n 个线程,一次最多 5 个 Activity 线程,等待所有线程完成后再继续

java - "Cannot reproduce"- Java 确定性多线程是否可能?

c# - .Net 应用程序的默认线程模型

.net - .Net事件有关集合更新