java - ThreadLocal 的使用如何降低可重用性

标签 java multithreading concurrency synchronization thread-local

广受好评的书JCIP这是关于 ThreadLocal 用法的:

It is easy to abuse ThreadLocal by treating its thread confinement property as a license to use global variables or as a means of creating "hidden" method arguments. Thread-local variables can detract from reusability and introduce hidden couplings among classes, and should therefore be used with care.

线程局部变量会降低可重用性并在类之间引入隐藏耦合是什么意思?

最佳答案

它们降低可重用性的方式与全局变量非常相似:当你的方法的计算依赖于方法外部的状态,但不作为参数传递(例如类字段)时,你的方法的可重用性较低,因为它与它所在的对象/类的状态紧密耦合(或者更糟,完全不同的类)。

编辑:好的,这里有一个例子可以让它更清楚。我使用 ThreadLocal 只是为了这个问题,但它通常适用于全局变量。假设我想在多个线程上并行计算前 N 个整数的总和。我们知道最好的方法是计算每个线程的局部总和,最后将它们相加。出于某种原因,我们决定每个 Taskcall 方法将使用一个 ThreadLocal sum 变量,该变量在不同的类中定义为全局变量(静态)变量:

class Foo {
    public static ThreadLocal<Long> localSum = new ThreadLocal<Long>() {
        public Long initialValue() {
            return new Long(0);         
        }
    };
}

class Task implements Callable<Long> {

    private int start = 0;
    private int end = 0;    

    public Task(int start, int end) {
        this.start = start;
        this.end = end;
    }

    public Long call() {
        for(int i = start; i < end; i++) {
            Foo.localSum.set(Foo.localSum.get() + i);
        }
        return Foo.localSum.get();
    }
}

代码工作正常并为我们提供了全局总和的预期值,但我们注意到类 Task 及其 call 方法现在严格耦合到 Foo 类。如果我想在另一个项目中重用 Task 类,我还必须移动 Foo 类,否则代码将无法编译。

虽然这是一个故意复杂化的简单示例,但您可以看到“隐藏”全局变量的危险。它还会影响可读性,因为阅读代码的其他人也必须搜索类 Foo 并查看 Foo.localSum 的定义是什么。您应该让您的类(class)尽可能独立。

关于java - ThreadLocal 的使用如何降低可重用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11283369/

相关文章:

java - 生成类型 IDENTITY 是如何工作的?它如何知道下一个要插入的主键是什么

python - 如何在正在运行的 python 脚本中启动其他脚本(新线程或进程?)

c# AsyncSocket 服务器需要锁定?

objective-c - 为什么 NSOperations 和 sleep 不能正常工作?

java - 使用 HttpClient 4.1 获取查询字符串

java - 使用 Scala BigDecimal 乘法和除法计算倒数

java - CompletableFuture.allOf 在抛出异常时取消其他 future

java - 在创建线程后将值从 Activity 传递到线程

c# - Task.Run(),传递参数给

java - 找不到库 : jvm. dll。这里发生了什么?