6

我已经阅读了关于 ThreadLocal 及其使用的 SO 线程的有趣讨论。

这个问题更倾向于设计时的选择。我的场景是这样的

如果我在 Web 应用程序中有一个值对象,几乎所有步骤都可能需要在同一线程中使用它。我可以想到两个界面设计选项,如下所示

方法 #1使用方法参数传递。

到目前为止,我一直专注于提出一个接口,该接口可以具有带有值对象接口参数的方法。

例如:

public interface SomeDataProcessorInterface {

public void processSomething(SomeValueObjectInterface vo);

}

public interface SomeValueObjectInterface extends Serializable {}

方法#2使用 ThreadLocal

在这种方法中,我可以有一个没有方法参数的接口,只需创建一个静态类来使用线程本地访问我的值对象。

例如:

public interface SomeDataProcessorInterface {

public void processSomething();

}

public interface SomeValueObjectInterface extends Serializable {}

public Class StaticClass {

    private static ThreadLocal<SomeValueObjectInterface> threadLocalVO = new ThreadLocal<SomeValueObjectInterface>();

     public static ThreadLocal getThreadLocal() {
        return threadLocal;
      }

哪种方法更好?为什么?

这些实现中的哪一个将有更少的内存泄漏机会?

这些实现中的哪一个对 Java 垃圾收集器有好处?

我阅读了其他线程中的一些要点,但是如果我从头开始,我仍然不清楚哪种方法更好。

4

3 回答 3

2

这是一个设计问题,取决于您的情况。

如果SomeValueObjectInterface在服务的业务逻辑上下文中有意义,那么(我相信)它应该是一个参数,但是如果您将其视为横切关注点(未实现为方面的方面)的数据,则它不是业务参数逻辑,然后使用ThreadLocal.

顺便说一句,不要忘记清除块ThreadLocal中的内容finally,否则您会遇到内存泄漏问题(通常很难找到)。

GC 没有区别,因为如果你不忘记清除,ThreadLocal那么两种方法中的对象都会在伊甸园中。

于 2013-10-10T21:57:43.400 回答
2

如果您可以在作为方法参数传递或通过 ThreadLocal 存储之间进行选择,则应在 99.99999% 的时间将其作为方法参数传递。ThreadLocal 存储的主要目的是处理间接调用某个方法的情况(即要求其他方法依次调用感兴趣的方法),需要将信息传递给内部方法,而middle 没有提供方便的渠道来传递该信息。如果没有“中间层”,可以简单地在内部方法的签名中添加附加参数(通常内部方法只会被有信息的代码调用,因此在方法定义和调用位置都添加参数)应该没有问题)。然而,在某些情况下,中间层存在并且必须使用。

对于示例,考虑一个ShapeCollection包含一个DrawAll调用Draw其所有形状的方法。应用程序定义了一些“很好地”渲染缓慢的形状,因此向每个窗口添加了一个选项,以选择是否让这些形状显示为占位符而不是详细渲染。如果Shape设计时考虑到这样的需求,它的Draw方法可以包含一个asPlaceHolder参数,并且ShapeCollection'sDrawAll可以接受这样的参数并将其传递给每个形状。但是,如果设计者Shape没有预料到这种需求,ShapeCollection则不会支持它。

如果每个花哨的形状对象的Draw方法仅用于更新一个特定窗口,则该形状可以保存对该窗口的引用,并使用该窗口的“使用占位符”选项来确定它应该如何呈现自己。但是,如果可能有多个窗口显示形状的视图,并且每个窗口都应该支持自己的渲染选项,那么这种方法可能不起作用。如果该Draw方法用于为剪贴板、打印机或其他介质渲染内容,这种方法也可能存在问题。让窗口的绘图代码构造一个DrawingOptions对象,创建一个对它的线程本地引用,调用DrawAll,然后删除该线程本地引用将是不优雅的,DrawAllDraw方法——否则是不可能的。

于 2013-10-11T18:12:47.817 回答
1

static TheadLocal如果您忘记删除元素,则使用s 可能会导致内存泄漏。您始终可以通过在从您的方法返回之前删除元素来避免这种情况。我不会推荐这种方法。

就目前而言,您的第一种方法已经是线程安全的,因为该参数仅对该方法调用是本地的。使用这个。

于 2013-10-10T21:04:02.900 回答