Java - ThreadLocal或并发对象池?

时间:2016-01-25 10:27:03

标签: java performance concurrency thread-local object-pooling

访问非线程安全对象可以接受哪种方法?

使用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);
    }
}

或您想要提供的其他方法?

重要因素是:

  • 性能
  • 内存使用
  • 垃圾收集

通常,每种方法的优点缺点是什么?

他们之间有明显的区别吗?

感谢。

编辑

Concurrent Object Pool使用Kryo的示例。

3 个答案:

答案 0 :(得分:3)

明显的区别当然是你有一个对象池,或者每个线程有一个专用对象。这具有各种后果,例如ThreadLocals可以完全有状态,因为它们仅由单个线程使用。合并对象可以是有状态的,但只能在他们被线程检出的时间内。

Some people think ThreadLocals are evil即使他们不是,他们仍然要求您在使用时成为智能Cookie。对象池的缺陷和优势在很大程度上取决于存储在其中的实际对象。

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

答案 1 :(得分:1)

粗略的经验法则可能是&#34; long&#34;每个线程通常对这些对象的租约。如果线程应该保持这些对象(接近)它们仍然在主动运行的整个时间,那么ThreadLocal&lt;&gt;可能是要走的路。另一方面,如果这些对象只是短暂地或间歇地使用,而不是整个线程的生命周期,那么对象池可能是最佳选择。

答案 2 :(得分:0)

一般情况下,我会使用

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

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