Ваш пример слишком сложен.Я создал другой, более простой, посмотрите код ниже.Если вы запустите его как есть, вы увидите строки в консоли, где 0 и 1 смешаны, как показано ниже:
11111111111111111111000000000000111111111111111111
11111111111111111111110000000000001111111111111111
Причина в том, что два потока изменяют одну и ту же переменную экземпляра "value" в синглтонеодновременно.
Теперь добавьте слово «synchronized» в оба метода «setValue» и «printValue» и запустите его снова.Вы увидите, что все строки состоят только из 0 или 1.Они больше не смешиваются.
00000000000000000000000000000000000000000000000000
11111111111111111111111111111111111111111111111111
Причина в том, что в любой момент только один из потоков изменяет переменную, поскольку «синхронизированный» предотвращает одновременный доступ к объекту-одиночке из разных потоков.
Вот код:
public class Main {
public static class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
private char[] value = new char[50];
private Singleton() {
}
public void printValue() {
for (int i = 0; i < value.length; i++) {
System.out.print(value[i]);
}
System.out.println();
}
public void setValue(String newValue) {
for (int i = 0; i < newValue.length() && i < value.length; i++) {
value[i] = newValue.charAt(i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// Ignore
}
}
}
}
public static void main(String[] args) {
final int MAX = 100000;
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < MAX; i++) {
Singleton.getInstance().setValue("00000000000000000000000000000000000000000000000000");
yield();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0; i < MAX; i++) {
Singleton.getInstance().setValue("11111111111111111111111111111111111111111111111111");
yield();
}
}
};
Thread thread3 = new Thread() {
@Override
public void run() {
for (int i = 0; i < MAX; i++) {
System.out.printf("%5d: ", i);
Singleton.getInstance().printValue();
yield();
}
}
};
thread1.start();
thread2.start();
thread3.start();
}
}