我认为你必须区分你已经存储在内存中的内容和代码执行。
在单例对象中,您有:
-
字段:它们存储在内存中。它们可以在多个线程之间共享,并且您不能保证它们将保持一致(除非您使它们同步)。
-
要调用的方法:可以从多个线程调用它们。每个执行都是独立的,并且是线程安全的,除非它们不正确地访问某些共享字段。
现在来回答你的问题:如果你在多个线程之间共享你的单例对象并同时访问它,那么每个线程都将执行单例对象的代码部分,包装在它自己的执行中。
此外,如果您编写一个基本上返回您正在执行的线程ID到单例方法中的线程ID,您将获得不同的ID,因为不同的线程正在执行它们自己的方法堆栈。无状态意味着你没有字段进入单例在它们之间共享!Thread.currentThread().getId();
关于无国籍和有国籍的一句话
无状态意味着 Bean 没有任何可修改的字段可以共享。这意味着你的对象中只有方法或/和静态的东西,所以你可以在任何地方使用它们,并且总是会返回相同的结果。您不必担心同步对字段的访问。
这是一个关于无状态的基本示例,假设您有一个只执行 sum 运算的类:
public class StatelessClass{
public int sum(int a, int b){
return a+b;
}
}
以同样的方式,你可以将其声明为抽象类(本身没有可实例化),并使其方法静态,这意味着你不需要它的任何实例来调用它的方法:
public abstract class StatelessClass{
/**
* I only sum objects
*/
public static int sum(int a, int b){
return a+b;
}
}
然后,您可以将其用作 ,这实际上与拥有 Singleton 对象本身非常相似,但不同之处在于,在 Singleton 中,您在应用程序中共享了一个唯一实例。StatelessClass.sum(1,1);
以同样的方式,拥有一个注入并提供对服务的访问的字段都不会被视为改变对象的状态:
public class StatelessServiceClass{
private Service service;
public int sum(int a, int b){
return service.sum(a,b);
}
public void setService(Service serv){
this.service=serv;
}
}
但是,具有可修改的字段会使 Object 具有状态:
public class StatefulClass{
//This fields make the object STATEFUL
private int totalSum = 0;
public int sum(int a, int b){
int sum = a + b;
totalSum = totalSum + sum;
if (totalSum > 100)
System.out.println("This thread "+Thread.currentThread().getId()+
+" got it!");
return sum;
}
}
由于可以同时由多个线程访问,因此应保证以同步方式访问。除非您这样做,否则打印的句子不能保证是真实的。sum
totalSum
所有这些在@BalusC的Threadsafety
文章中也得到了适当的解释。