私には、すべての静的メソッドはJavaWebアプリケーションのコンテキスト内にあるべきだと言った友人がいsynchronized
ます。本当?私はこれに関して他の多くのスタックオーバーフローページを読みました。私が信じるようになったのは、次の場合にのみ同期する必要があるということです。
- 複数のスレッド(スレッドプールを備えたSevletコンテナの場合と同様)
- シングルClassLoader
- セッションデータであろうと静的メンバーデータであろうと、スレッド間で共有されるデータ。
- 共有データは変更可能である必要があります。読み取り専用データは共有しても問題ありません。
これに基づいて、静的メンバーは同期する必要があると思いますが、静的メソッドは同期しないでください。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadTest {
static String staticString = "";
// This static method is safe b/c it only uses local data.
// It does not use any shared mutable data.
// It even uses a string builder.
static String safeStaticMethod(String in) {
// This also proves that StringBuilder is safe
// When used locally by a thread.
StringBuilder sb = new StringBuilder();
sb.append("Hello: ");
sb.append(in);
return sb.toString();
}
// This static method is not safe b/c it updates and reads
// shared mutable data among threads.
// Adding synchronized will make this safe.
static String unsafeStaticMethod(String in) {
staticString = in;
StringBuffer sb = new StringBuffer();
sb.append("Hello: ");
sb.append(staticString);
return sb.toString();
}
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.staticMethodWithLocalData();
test.staticMethodWithStaticData();
}
public void staticMethodWithLocalData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!safeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("safeStaticMethod at " + index);
}
}
}
});
}
public void staticMethodWithStaticData() {
ExecutorService executor = Executors.newFixedThreadPool(2);
final int iterations = 100000;
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread1").equals("Hello: Thread1")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
executor.submit(new Runnable() {
@Override
public void run() {
for (int index = 0; index < iterations; ++index) {
if (!unsafeStaticMethod("Thread2").equals("Hello: Thread2")) {
System.out.println("unsafeStaticMethod at " + index);
}
}
}
});
}
}
このコードはポイントを証明していますか?
編集:これは、要点を証明するために私がハックした使い捨てコードのほんの一部です。