4

哪种方法更适合访问非线程安全对象

使用ThreadLocal对象:

static final ThreadLocal<NonThreadSafeParser> PARSER_THREAD_LOCAL = new ThreadLocal<NonThreadSafeParser>() {
    @Override
    protected NonThreadSafeParser initialValue() {
        return new NonThreadSafeParser();
    }
};

void parse(String input) {
    PARSER_THREAD_LOCAL.get().parse(input);
}

使用并发对象池

static final ConcurrentObjectPool<NonThreadSafeParser> PARSER_POOL = new ConcurrentObjectPool<>();

void parse(String input) {
    NonThreadSafeParser parser = PARSER_POOL.borrow();
    try {
        parser.parse(input);
    } finally {
        PARSER_POOL.release(parser);
    }
}

或您想提供的其他方法?

重要因素是:

  • 表现
  • 内存使用情况
  • 垃圾收集

一般来说,每种方法的优缺点什么

它们之间有什么明显的区别吗?

谢谢。

编辑

Kryo使用的并发对象池的示例。

4

3 回答 3

5

明显的区别当然是你要么有一个对象池,要么每个线程都有一个专用对象。这有各种后果,例如ThreadLocals可以是完全有状态的,因为它们仅由单个线程使用。池化对象可以是有状态的,但仅在它们被线程签出期间。

有些人认为 ThreadLocals 是邪恶的,即使他们不是,他们仍然要求你在使用它们时是一个聪明的 cookie。对象池的缺陷和优势在很大程度上取决于存储在其中的实际对象。

所以总而言之:这取决于并且它有点基于意见。再一次,我们遇到了一个没有绝对答案的软件开发问题,尽管人们喜欢认为我们正在处理一门精确的科学。

于 2016-01-25T12:08:00.023 回答
1

粗略的经验法则可能是每个线程通常在这些对象上拥有多长时间的租约。如果线程应该在(接近)它们一直在积极运行的整个过程中保持这些对象,那么 ThreadLocal<> 可能是要走的路。另一方面,如果与整个线程的生命周期相比,这些对象只是短暂或间歇性地使用,那么对象池可能是可行的方法。

于 2017-08-08T13:24:30.810 回答
0

一般来说,我会使用

ThreadLocal- 如果该对象仅属于该线程但不能是私有的并且需要跨层访问。它可能是与当前线程相关的上下文。

ThreadPool- 当我需要共享有限的资源或需要同步多个线程之间的通信时。

于 2016-01-25T11:51:26.153 回答