我正在Java中探索Thread local。我无法理解为什么我们需要这门课。如果我只是简单地将一个新对象传递给每个线程来执行,我可以实现相同的动机,如果我使用initialValue()就会发生同样的事情。我只是在initialvalue()中为每个线程返回一个新对象。
但是说我有两个线程,ThreadOne:A和ThreadTwo B.现在我希望他们拥有自己的SimpleDateFormat类的副本。我可以通过在ThreadLocal类中扭曲SimpleDateFormat的对象然后使用initialValue()来执行此操作,我可以返回新的SimpleDateFormat(“yyyyMMdd HHmm”);.同样的动机我可以通过创建两个新的SimpleDateFormat对象和p [每个向ThreadOne分别一个:A.和ThreadTwo:B。ThreadLocal如何帮助我额外的
此致
答案 0 :(得分:4)
对于您的问题,已经有一些很好的例子here。
但我试着解释第二部分:
但是说我有两个主题,ThreadOne:A和ThreadTwo B.现在我想要 他们拥有SimpleDateFormat类的副本。我可以 这是通过在ThreadLocal类中扭曲SimpleDateFormat的对象来实现的 然后使用initialValue()我可以返回new SimpleDateFormat(“yyyyMMdd HHmm”);.同样的动机我可以实现 创建两个新的SimpleDateFormat对象和p [每个对应一个 ThreadOne:A。和ThreadTwo:B。ThreadLocal如何帮助我额外的
通常,您需要使用特定格式格式化日期,并且创建SimpleDateFormat
对象一次是个好主意(而不是每次需要格式化时创建新的SimpleDateFormat
一个约会)。
所以你可能会有这样的事情:
public class DateUtils {
private final static DateFormat dateFormat = new SimpleDateFormat("dd-mm-yyyy");
public String formatDate(Date date) {
return dateFormat.format(date);
}
}
如果多个线程同时调用formatDate(...)
(您可能会得到奇怪的输出或exceptions
),因为SimpleDateFormat
不是Thread-Safe
,这将失败。为了使其成为线程安全的,您可以使用ThreadLocal
:
public class DateUtils {
private final ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("dd-mm-yyyy");
}
};
public String formatDate(Date date) {
return dateFormat.get().format(date);
}
}
现在,formatDate()方法的每个线程(或调用)都将在本地副本上工作,并且不会相互干扰。这给你线程安全的行为。
答案 1 :(得分:1)
线程局部存储在单个线程的上下文中用于全局变量。
考虑这个例子:你编写了一个用于处理用户请求的多线程程序。多个用户可以同时发起请求;您的系统为每个用户使用一个线程。
当用户请求到达时,系统会找出来自的用户,并为该用户创建UserPermissions
对象的实例。
有几种方法可以使该对象可用于正在运行的程序。一种方法是将UserPermissions
传递给可能需要它的每个方法,也可以传递给直接或间接调用可能需要它的方法的每个方法。这可能有问题,尤其是在使用回调的情况下。
如果你的程序没有多线程,你可以在全局变量中设置UserPermissions
。遗憾的是,您不能这样做,因为多个用户请求可能同时处于活动状态。
这是线程本地存储的用武之地:创建用户权限的进程在线程本地存储中设置UserPermissions
对象,并将其留在那里直到请求处理结束。这样,所有方法都可以根据需要抓取UserPermissions
,而不必将它们作为方法参数传递。
答案 2 :(得分:0)
您将使用ThreadLocal
将“数据”传递给特定的主题
例如,您有一个方法doSomething(SomeObject a, SomeOtherObject b);
您可以通过线程本地而不是a
和b
答案 3 :(得分:0)
本地线程是实现dynamic scoping的廉价方式。使用动态范围,在评估代码块期间存在绑定。在这种情况下,绑定在特定线程的执行期间存在。早期的lisps支持动态范围,但它很少有意义,所以大多数现代编程语言不支持它,除了通过线程本地。
动态作用域/线程局部文件可用于维护普遍的上下文信息,例如:
有一系列名为“context-oriented programming”的研究旨在更好地支持编程语言中的这些问题。论文“context-oriented programming: beyond layers”显示了一些进一步的例子。