Параллелизм Java - потоки не заканчивают циклы - PullRequest
0 голосов
/ 03 января 2019

Я изучаю основы параллелизма на 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.

Подводя итог, мои вопросы:

  1. Почему вывод моего кода отличается каждый раз?
  2. Почему петли в потоках не заканчивают свою работу?
  3. Почему мой вывод отличается от приведенного в книге? **

** - Дополнительно

1 Ответ

0 голосов
/ 03 января 2019

не знаю, как книга ожидает, что это сработает, но ваш экземпляр Accum не является поточно-ориентированным. следовательно, каждый раз, когда вы запускаете его, вы можете получить другой ответ. Если синхронизировать updateCounter () и getCount (), он должен работать надежно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...