Это упражнение прямо из SCJP от Kathy Seirra и Bert Bates
Синхронизация блока кода
В этом упражнении мы попытаемся синхронизировать блок кода. Внутри этого блока кода мы получим блокировку объекта, чтобы другие потоки не могли его модифицировать, пока выполняется блок кода. Мы создадим три потока, которые будут пытаться манипулировать одним и тем же объектом. Каждый поток будет выводить одну букву 100 раз, а затем увеличивать эту букву на единицу. Объект, который мы будем использовать, - StringBuffer.
Мы могли бы синхронизировать объект String, но строки не могут быть изменены один раз они создаются, поэтому мы не сможем увеличивать букву без создания нового объекта String. Конечный результат должен содержать 100 As, 100 Bs и 100 Cs в непрерывных строках.
- Создайте класс и расширьте класс Thread.
- Переопределить метод run() Thread. Здесь синхронизируется блок кода будет идти.
- Чтобы наши три объекта потока могли совместно использовать один и тот же объект, нам нужно будет создать конструктор, который принимает объект StringBuffer в аргументе.
- Синхронизированный блок кода получит блокировку на StringBuffer объект из шага 3.
- Внутри блока выводить StringBuffer 100 раз, а затем увеличивать письмо в StringBuffer. Вы можете проверить главу 6 для StringBuffer методы, которые помогут с этим.
- Наконец, в методе main() создайте один объект StringBuffer, используя буквы A, затем создайте три экземпляра нашего класса и запустите все три из них.
Я написал следующий класс для вышеуказанного упражнения (вместо 100 я печатаю 10 символов)
class MySyncBlockTest extends Thread {
StringBuffer sb;
MySyncBlockTest(StringBuffer sb) {
this.sb=sb;
}
public static void main (String args[]) {
StringBuffer sb = new StringBuffer("A");
MySyncBlockTest t1 = new MySyncBlockTest(sb);
MySyncBlockTest t2 = new MySyncBlockTest(sb);
MySyncBlockTest t3 = new MySyncBlockTest(sb);
t1.start();
t2.start();
t3.start();
}
public void run() {
synchronized(this) {
for (int i=0; i<10; i++) {
System.out.print(sb);
}
System.out.println("");
if (sb.charAt(0)=='A')
sb.setCharAt(0, 'B');
else
sb.setCharAt(0, 'C');
}
}
}
Я ожидал, что вывод будет похож на следующий (10 As, 10 Bs и 10 Cs), но не получил его.
AAAAAAAAAA
BBBBBBBBBB
CCCCCCCCCC
Вместо этого я получил различные выходные данные, например, следующие три потока: получив шанс попасть в цикл до того, как другой закончит.
AAAAAAAAAAAAAAAAAA
ABB
ACCCCCCCC
Мой вопрос: почему синхронизированный блок в методе запуска не работает?