すでにメモリに保存したものとコードの実行を区別する必要があると思います。
シングルトン オブジェクトには次のものがあります。
- フィールド: それらはメモリに保存されます。それらは複数のスレッド間で共有でき、一貫性を保つ保証はありません (同期化しない限り)。
- 呼び出されるメソッド: 複数のスレッドから呼び出すことができます。共有フィールドに不適切にアクセスしない限り、各実行は独立しており、スレッドセーフです。
あなたの質問に来てください:シングルトンオブジェクトを複数のスレッド間で共有し、同時にアクセスすると、すべてのスレッドがシングルトンオブジェクトのコード部分を実行し、独自の実行にラップされます。
また、Thread.currentThread().getId();
基本的に実行中のスレッド ID を返す a をシングルトンのメソッドに記述すると、異なるスレッドが独自のメソッド スタックを実行しているため、異なる ID を取得します。ステートレスであることは、それらの間で共有されるシングルトンにフィールドがないことを意味します!
ステートレスとステートフルについて一言
ステートレスとは、Bean に共有する変更可能なフィールドがないことを意味します。つまり、オブジェクトにはメソッドまたは静的なものしかないため、どこでも使用でき、常に同じ結果が返されます。フィールドへのアクセスの同期について心配する必要はありません。
これはstatelessに関する基本的な例です。合計演算のみを実行するクラスがあるとします。
public class StatelessClass{
public int sum(int a, int b){
return a+b;
}
}
同様に、それを抽象クラス (それ自体はインスタンス化できない) として宣言し、そのメソッドをstaticにすることができます。つまり、そのメソッドを呼び出すためにそのインスタンスは必要ありません。
public abstract class StatelessClass{
/**
* I only sum objects
*/
public static int sum(int a, int b){
return a+b;
}
}
次に、それを として使用できます。これは実際にはSingletonStatelessClass.sum(1,1);
オブジェクト自体を持つのと非常に似ていますが、Singleton ではアプリケーションで共有される一意のインスタンスがあるという違いがあります。
同様に、注入されてサービスへのアクセスを提供するフィールドを持つことも、オブジェクトの状態を変更するとは見なされません。
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;
}
}
ただし、変更可能なフィールドを持つと、オブジェクトはステートフルになります。
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
部分でも適切に説明されています。