Java中的功能对等

Moh*_*s A 7 java multithreading stateless thread-safety comparator

我正在阅读《有效的Java》,遇到了约书亚·布洛赫(Joshua Bloch)建议类似的情况

class MyComparator extends Comparator<String>{
    private MyComparator(){}
    private static final MyComparator INSTANCE = new MyComparator();

    public int compare(String s1,String s2){ 
        // Omitted
    }
}
Run Code Online (Sandbox Code Playgroud)

XYZComparator是无状态的,没有字段。因此,该类的所有实例在功能上都是等效的。因此,节省不必要的对象创建应该是一个单例

因此,如果它没有字段那么为它指向的任何类创建一个静态的final 总是安全的吗?从两个线程并行调用时,这不会引起多线程问题吗?或者我误解了一些基本知识。如果没有共享字段,就像每个线程都有执行的自主权吗?Objectcompare

And*_*lko 5

那么,如果它没有字段,那么创建它所指向的任何类的静态最终对象总是安全的吗?

我敢说是的。没有字段会使类无状态,因此是不可变的,这在多线程环境中总是可取的。

无状态对象始终是线程安全的。

不可变对象始终是线程安全的。

摘自 Java 并发实践:

由于线程访问无状态对象的动作不会影响其他线程中操作的正确性,因此无状态对象是线程安全的。

无状态对象始终是线程安全的。

大多数 servlet 可以无状态实现的事实大大减少了使 servlet 线程化的负担?安全的。只有当 servlet 想要记住从一个请求到另一个请求的内容时,线程安全要求才成为一个问题。

...

不可变对象是一种在构造后其状态不能改变的对象。不可变对象本质上是线程安全的;它们的不变量是由构造函数建立的,如果它们的状态不能改变,这些不变量总是成立的。

不可变对象始终是线程安全的。

不可变对象很简单。它们只能处于一种状态,这是由构造函数仔细控制的。程序设计中最困难的元素之一是对复杂对象的可能状态进行推理。另一方面,对不可变对象的状态进行推理是微不足道的。


当从两个线程并行调用比较时,这不会导致多线程问题吗?

不。每个线程都有自己的堆栈,其中存储局部变量(包括方法参数)。线程的堆栈不是共享的,因此无法并行地弄乱它。

另一个很好的例子是无状态 servlet。从那本伟大的书中再摘一段。

@ThreadSafe
public class StatelessFactorizer implements Servlet {
    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        encodeIntoResponse(resp, factors);
    }
}
Run Code Online (Sandbox Code Playgroud)

StatelessFactorizer与大多数 servlet 一样,是无状态的:它没有字段,也没有引用来自其他类的字段。特定计算的瞬态仅存在于存储在线程堆栈中的局部变量中,并且只能由执行线程访问。一个线程访问 aStatelessFactorizer不能影响另一个线程访问相同的结果StatelessFactorizer;因为两个线程不共享 state,就好像它们正在访问不同的实例。


如果没有共享字段,是否每个线程都有执行自主权?

每个线程都有自己的程序计数器、堆栈和局部变量。有一个术语“线程限制”,它的一种形式称为“堆栈限制”。

堆栈限制是线程限制的一种特殊情况,其中对象只能通过局部变量访问。正如封装可以更容易地保留不变量一样,局部变量可以更容易地将对象限制在线程中。局部变量本质上仅限于执行线程;它们存在于执行线程的堆栈中,其他线程无法访问。

阅读: