Я изучаю основы параллелизма на Java и застрял с одной проблемой в этом примере ниже. Есть два потока, которые должны работать одновременно и завершать свои циклы, работая с каким-то глобальным статическим объектом. Я ожидал, что один поток может закончиться раньше другого и вывести другое значение, но я не ожидал, что оба потока будут печатать одно и то же значение, что говорит о том, что оба они не закончили свои циклы до вывода на печать.
Код:
public class TestThreads {
public static void main(String[] args) {
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class Accum {
private static Accum a = new Accum();
private int counter = 0;
private Accum() {
}
public static Accum getAccum() {
return a;
}
public int getCount() {
return counter;
}
public void updateCounter(int add) {
counter += add;
}
}
class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run() {
for(int x=0; x < 98; x++) {
a.updateCounter(1000);
try {
Thread.sleep(50);
} catch(InterruptedException ex) { }
//System.out.println("index in one = " + x);
}
System.out.println("one " + a.getCount());
}
}
class ThreadTwo implements Runnable {
Accum a = Accum.getAccum();
public void run() {
for(int x=0; x < 99; x++) {
a.updateCounter(1);
try {
Thread.sleep(50);
} catch(InterruptedException ex) { }
//System.out.println("index in two = " + x);
}
System.out.println("two " + a.getCount());
}
}
Почему это происходит? Когда я попытался выполнить отладку с помощью операторов print (прокомментировано в приведенном выше коде), все стало работать как положено.
Мой вывод: (каждый раз по-разному, это тоже странно)
один 82067
два 82067
Это на самом деле код-пазл из книги "Head First Java" (2nd Edition), но автор предоставляет тот же код, что и выше, в качестве решения для другого поведения.
Вывод книги: (тот же код, что и выше)
один 98098 два 98099
Объяснение книги:
Потоки из двух разных классов обновляют один и тот же объект в
третий класс, потому что оба потока обращаются к одному экземпляру
Accum.
Подводя итог, мои вопросы:
- Почему вывод моего кода отличается каждый раз?
- Почему петли в потоках не заканчивают свою работу?
- Почему мой вывод отличается от приведенного в книге? **
** - Дополнительно