【问题标题】:Java, create a cache of re-usable thread unsafe objectsJava,创建可重用线程不安全对象的缓存
【发布时间】:2020-01-22 07:13:13
【问题描述】:

有时在 java 中我有线程不安全且创建成本高的对象。我想为这些对象创建一个缓存,因此我不需要重新创建它们,但它还必须防止对同一对象的并发访问。

例如,我可能有DateFormat,创建它的成本太高,但我不能共享一个DateFormat。为了争论,假设我不能使用线程安全的DateFormat

如果能够像这样创建一些缓存,那就太棒了:

Cache<DateFormat> cache = new Cache(() -> dateFormatCreator());
// and now make use of a dateFormat that might be created for this call 
// or it might be an existing one from the cache.
cache.withExclusiveAccessToObject(dateFormat -> {
   // use the dateFormat here, it is not in use by any other thread at the same time.
   // new dateFormats can be created on the fly as needed.
});

我还应该提到ThreadLocal 并不理想,因为我无法确保线程会被重用。

【问题讨论】:

  • 有问题吗? / 对于一个小对象,您可以只使用ThreadLocal(这对它们来说是唯一的好用处)。
  • 听起来你想要一个对象池,例如ViburStormpot.
  • 不错的@BenManes 现在我被宠坏了。

标签: java caching


【解决方案1】:

我相信你可以走两条路:

选项 1

为每个线程维护一个对象

如果您从有限且定义明确的线程集访问昂贵的对象(读取,使用线程池而不是每次都创建线程,这在许多应用程序中无论如何都会发生),这可能会起作用。

在这种情况下,您可以使用ThreadLocal。由于在一个线程中,所有内容都应该是连续的,因此您可以将线程不安全的对象保存在本地线程中。

您可以将 ThreadLocal 视为每个线程维护一个昂贵对象的专用实例的映射。

选项 2

在 M 个线程之间共享一个(或通常是 N 个)对象,以便 N

我不知道有现成的解决方案,毕竟它是您想要维护的对象,但通常很容易包装您自己的实现,这将提供对对象的某种锁定/同步访问您的对象类型。

实现的想法范围可能会有所不同。作为一个想法:您可以使用运行时/构建时生成的代理包装实际对象,使其有效地线程安全:

public interface IMyObject {
    void inc();
    void dec();
}

// this is an object that you would like to make thread safe
public class MyActualObject implements IMyObject {
    private int counter = 0;
    void inc() {counter++;}
    void dec() {counter--;}
}

public class MyThreadSafeProxy implements IMyObject {

    private IMyObject realObject;

    public MyThreadSafeProxy(IMyObject realObject) {
        this.realObject = realObject;
    }

    @Override
    public synchronized void inc() {
       realObject.inc();
    }

    @Override 
    public syncrhonized void dec() {
       realObject.dec();
    }
}

您可以将它们包装在MyThreadSafeProxy中,而不是存储MyObject-s

也可以自动生成这样的代理:参见cglib 框架或Dynamic Proxies (java.lang.Proxy class)

根据我的经验,通常选项 1 更可取,除非您使用的对象过于昂贵,以至于如果池中有 N 个线程,您就无法真正支持内存中的 N 个对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多