java - 线程特定的单例实例

标签 java multithreading singleton

我正在寻找一种编写实例工厂的好方法,该工厂为每个线程创建一个类的实例(换句话说:特定于线程的单例)。

为了清楚起见,让我添加一些示例代码:

首先,一个一般定义工厂的接口(interface):

public interface Factory<T> {
    public T create();
}

对于普通的单例,我可以创建一个包装另一个工厂的接口(interface)的实现:

public class SingletonFactory<T> implements Factory<T> {

    private final Factory<T> factory;
    private T instance = null;

    public SingletonFactory(Factory<T> factory) {
        this.factory = factory;
    }

    @Override
    public T create() {
        if (instance==null) instance = factory.create();
        return instance;
    }
}

基本上,第一次调用 create() 时,此调用将转发到提供的工厂以创建对象的一个​​实例。该实例已被缓存,以后对 create() 的所有调用都将返回同一实例。我需要做的就是确保每个对象类型 T 周围只有一个 SingletonFactory 实例。

假设我想每个线程提供一个对象实例:我可以这样做:

public class ThreadSingletonFactory<T> implements Factory<T> {

    private final Factory<T>     factory;
    private final Map<Thread, T> instance;

    public ThreadSingletonFactory(Factory<T> factory) {
        this.factory  = factory;
        this.instance = new HashMap<Thread, T>();
    }

    @Override
    public T create() {
        Thread thread = Thread.currentThread();
        T result = instance.get(thread);
        if (result==null) {
            result = factory.create();
            instance.put(thread, result);
        }
        return result;
    }
}

现在,每次调用 create() 时,该类都会在其实例映射中查找当前线程,以查看该线程是否已创建实例。如果没有,它会创建一个新的并记住它。

我发现这种幼稚的方法存在一些问题:

  1. HashMap 不是线程安全的,这可能不是问题,因为没有两个线程会操作同一个键,但我不确定。我可以使用 Collections.synchronizedMap使其线程安全,但我想避免这种情况,因为它意味着到处都有大量同步,这可能会对性能产生重大影响。
  2. 如果应用程序不使用线程池,但不断生成大量短期的新线程,则映射将增长到潜在的巨大尺寸,并用不再需要的实例阻塞大量内存。

我正在考虑使用 WeakHashMap相反,它是为了解决第二个问题,因为一旦 key 不再使用,它​​允许其条目被垃圾收集,但我也遇到了两个潜在的问题:

  1. 查看 OpenJDK Source ,通过 expungeStaleEntries() 释放未使用的 key 每次我调用 get(...)put(...) 时都会启动并涉及潜在的多个同步操作,我再次希望避免这种情况性能原因。
  2. 我仍然不确定是否还需要将映射包装到同步映射中以确保不会遇到并发问题。

是否有一种不同的解决方案,最好不需要使用任何 同步(假设Factory.create()的所有实现都是线程安全)?如果它确实需要以某种方式管理并发,我更希望它通过 java.util.concurrent.atomic 中的类来这样做。 .

最佳答案

根据@JBNizet 和@SotiriosDelimanolis 的建议,ThreadLocal可能会成功。

我还没有测试过,但可能就是这样了?

public class ThreadSingletonFactory<T> implements Factory<T> {

    private final ThreadLocal<T> instance;

    public ThreadSingletonFactory(final Factory<T> factory) {
        this.instance = new ThreadLocal<T>() {
            @Override
            protected T initialValue() {
                return factory.create();
            }
        };
    }

    @Override
    public T create() {
        return instance.get();
    }
}

关于java - 线程特定的单例实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24599136/

相关文章:

Java 忽略类路径

java - Spring MVC 的有效 AJAX 请求

java - AsyncTask-Method getText 必须从 UI 线程调用

java - 我需要使 Singleton 类中的每个方法同步吗?

java - 为什么没有立即收集 'invisible' 对象?

java - 如何确定 CPU 绑定(bind)任务在运行时的最佳线程数?

java - 我怎样才能让interrupt()工作?

php - 单例 PDO 模型 - 层次结构

c++ - boost 单例

java - 为什么 FindBugs 显示冗余空检查警告