ThreadLocal vs Parameter Passing - 在接口设计中选择哪个? 在多线程编程中,我们经常需要在不同的线程之间共享数据。在接口设计中,有两种常见的方式来实现线程间数据共享:ThreadLocal和参数传递。 ThreadLocal是一种Java线程级别的变量,它允许我们在一个线程中存储和访问数据,而其他线程无法访问。这种方式适用于需要在线程之间共享数据,但不想通过参数传递的情况。 参数传递是另一种常见的方式,它通过方法或函数的参数将数据从一个线程传递到另一个线程。这种方式

9 浏览
0 Comments

ThreadLocal vs Parameter Passing - 在接口设计中选择哪个? 在多线程编程中,我们经常需要在不同的线程之间共享数据。在接口设计中,有两种常见的方式来实现线程间数据共享:ThreadLocal和参数传递。 ThreadLocal是一种Java线程级别的变量,它允许我们在一个线程中存储和访问数据,而其他线程无法访问。这种方式适用于需要在线程之间共享数据,但不想通过参数传递的情况。 参数传递是另一种常见的方式,它通过方法或函数的参数将数据从一个线程传递到另一个线程。这种方式

我已经阅读了关于ThreadLocal及其使用的以下SO讨论。这些问题更多地涉及设计时的选择。我的场景是这样的:如果我在Web应用程序中有一个值对象,可能需要在同一个线程中的几乎所有步骤中使用。我可以考虑以下两种接口设计选项:

方法一:使用方法参数传递。

我迄今为止专注于设计一个接口,该接口可以具有参数为值对象接口的方法。

例如:

public interface SomeDataProcessorInterface {
public void processSomething(SomeValueObjectInterface vo);
}
public interface SomeValueObjectInterface extends Serializable {}

方法二:使用ThreadLocal。

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

例如:

public interface SomeDataProcessorInterface {
public void processSomething();
}
public interface SomeValueObjectInterface extends Serializable {}
public Class StaticClass {
    private static ThreadLocal threadLocalVO = new ThreadLocal();
     public static ThreadLocal getThreadLocal() {
        return threadLocal;
      }

哪种方法更好?为什么?

这些实现中哪一种更不容易出现内存泄漏?

这些实现中哪一种对Java垃圾回收器更好?

我已经阅读了其他讨论中的一些观点,但如果我从头开始,我仍然不清楚哪种方法更好。

0
0 Comments

在接口设计中,我们经常会面临一个选择:是使用ThreadLocal还是参数传递。这个问题的出现是因为在使用静态的ThreadLocal时,如果忘记移除元素,就会导致内存泄漏的风险。虽然我们可以在方法返回之前移除元素来避免这个问题,但并不推荐这种做法。相比之下,第一种方法已经是线程安全的,因为参数只会在方法调用时存在。因此,我建议使用这种方法。

感谢你的回复。我明白你提到的释放线程本地变量的问题。在线程执行结束时,必须在finally块中调用threadLocal.remove来移除它。

0
0 Comments

在接口设计中,我们需要考虑使用ThreadLocal还是参数传递。这是一个设计问题,取决于具体情况。

如果SomeValueObjectInterface在服务的业务逻辑上有意义,那么它应该作为一个参数传递;但如果你认为它只是为了处理横切关注点(即不以切面的形式实现的关注点),并且不是业务逻辑的参数,那么可以使用ThreadLocal

另外,不要忘记在finally块中清除ThreadLocal,否则可能会导致内存泄漏问题(这类问题通常很难发现)。

至于垃圾回收方面,没有区别,因为如果不忘记清除ThreadLocal,那么两种方法中的对象都会被放到伊甸区(Eden)。

提到横切关注点,我认为使用ThreadLocal是很有意义的。

0
0 Comments

在接口设计中,出现了如何选择使用ThreadLocal还是参数传递的问题。99.99999%的情况下,应该选择将信息通过方法参数传递。ThreadLocal存储的主要目的是处理间接调用方法的情况,即通过其他方法间接调用所需的方法,需要将信息传递给内部方法,而中间方法没有提供方便的传递信息的通道。如果没有“中间层”,可以简单地将额外的参数添加到内部方法的签名中(通常只有具有信息的代码会调用内部方法,因此在方法定义和调用点添加参数应该没有问题)。然而,在某些情况下,存在中间层并且必须进行处理。

例如,考虑一个包含DrawAll方法的ShapeCollection,它调用所有形状的Draw方法。应用程序定义了一些渲染“漂亮”速度较慢的形状,并为每个窗口添加了一个选项,可以选择将这些形状显示为占位符而不是详细渲染。如果Shape在设计时考虑到了这些需求,它的Draw方法可以包含一个asPlaceHolder参数,并且ShapeCollectionDrawAll可以接受此参数并将其传递给每个形状。然而,如果Shape的设计者没有预料到这种需要,ShapeCollection将不支持它。

如果每个花哨的形状对象的Draw方法只用于更新一个特定的窗口,那么形状可以持有对该窗口的引用,并使用该窗口的“使用占位符”选项来确定如何渲染自己。然而,如果可能有多个窗口显示形状的视图,并且每个窗口都应支持自己的渲染选项,那么这种方法可能行不通。如果Draw方法用于为剪贴板、打印机或其他介质渲染物品,这种方法也可能出现问题。虽然在窗口的绘制代码中构造一个DrawingOptions对象,创建一个线程局部引用,调用DrawAll,然后擦除该线程局部引用并不优雅,但它提供了一种方式,使得对DrawAll的调用可以向内部的Draw方法传递绘制选项,否则是不可能的。

我理解你的观点。在线程无法预料到接口的变化的情况下,ThreadLocal可以作为一种补丁的选择。

0