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

Inq*_*ive 7 java concurrency multithreading synchronization thread-local

备受好评的书籍JCIP对ThreadLocal的使用说明了这一点:

通过将其线程限制属性视为使用全局变量的许可或作为创建"隐藏"方法参数的方法,很容易滥用ThreadLocal.线程局部变量可能会降低可重用性并在类之间引入隐藏的耦合,因此应谨慎使用.

说Thread-local变量可以减少可重用性并在类之间引入隐藏的耦合是什么意思?

Tud*_*dor 11

它们以与全局变量相同的方式减少可重用性:当方法的计算依赖于方法外部的状态,但不作为参数传递(例如类字段)时,您的方法不太可重用,因为它紧密耦合到它所在的对象/类的状态(或者更糟糕的是,完全在另一个类上).

编辑:好的,这是一个让它更清晰的例子.我ThreadLocal只是为了问题而使用,但它一般适用于全局变量.假设我想在几个线程上并行计算前N个整数的总和.我们知道最好的方法是计算每个线程的本地总和,然后在最后总结它们.出于某种原因,我们决定call每个方法Task将使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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