Arhn - архитектура программирования

Выводить числа последовательно, используя два потока

Это вопрос интервью, и я не думаю, что он имеет какое-либо отношение к практическим проблемам реальной жизни. Мне нужно печатать числа 12345.... последовательно, но условие состоит в том, что я должен печатать его, используя два потока, один из которых отвечает за печать нечетных чисел, а другой - за четные числа.
до сих пор я придумал это решение.

    package junk.concurrency;

public class PrintEvenOddTester {

    public static void main(String... args) {
        TaskEvenOdd t = new TaskEvenOdd(10);
        Thread t1 = new Thread(t, "odd printer");
        Thread t2 = new Thread(t, "even printer");
        t1.start();
        t2.start();
    }
}

class TaskEvenOdd implements Runnable {

    private int max;
    private boolean isOdd = true;
    private int number = 1;

    TaskEvenOdd(int max) {
        this.max = max;
    }

    synchronized void printEven(int number) { // sync on runnable itself

        while (isOdd) { // if odd is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Even:" + this.number);  // LINE-1
        isOdd = true;
        this.number++;                             // LINE-2
        notifyAll();
    }

    synchronized void printOdd(int number) { // sync on runnable itself
        while (!isOdd) { // if even is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Odd:" + this.number);    // LINE-3
        this.number++;                               // LINE-4
        isOdd = false;
        notifyAll();
    }

    @Override
    public void run() {

        while (number <= max) {

            if (Thread.currentThread().getName().equals("even printer")) {
                printEven(number);
            } else {
                printOdd(number);
            }
        }
    }
}

1
при написании этого кода я заметил одно странное поведение, которое не понял. Если в LINE-1,2,3,4 в приведенном выше коде я пишу number вместо this.number, моя числовая переменная экземпляра не увеличивается, и код просто печатает бесконечное количество единиц.
Я предполагаю, что оба метода printEven и printOdd вызываются для самого исполняемого экземпляра, тогда почему его значение не увеличивается. Я попытался сделать number изменчивым, но все равно это привело к тому же результату.
2
Также я вижу, что числа печатаются до 11, а не до 10. Я понимаю, почему это происходит (последний вызов printOdd получает уведомление о последнем вызове printEven (который печатает 10), поэтому печатает 11), один из способов избежать этого - проверять номер каждый раз перед печатью и смотреть, находится ли он в пределах лимита, но я хотел знать, что было бы лучше способ преодолеть это.
Спасибо.


Параметр метода EDIT number полностью лишний и может быть опущен. Это условие if(this.max>=number) можно использовать перед печатью числа.


  • Если я когда-нибудь задам этот вопрос в интервью, я хочу получить ответ: «Это очень глупо». Если вы хотите, чтобы какая-либо программа выполняла последовательность действий в определенном порядке, правильный способ добиться этого — выполнять все действия в одном потоке. Если кто-нибудь когда-нибудь задаст мне этот вопрос, а затем скажет: «Хорошо, но делайте это в любом случае», я создам общее решение, в котором любое количество потоков по очереди передает токен от одного к другому через BlockingQueues : Когда поток получает токен, наступает его очередь. Когда это будет сделано, он передает токен следующему потоку. 14.08.2016

Ответы:


1

1

Ваша проблема в том, что параметр вашего метода также называется number. Так что это затенение поля вашего класса! Итак, когда вы опускаете, вы включаете параметр; который просто не имеет никакого реального эффекта!

Есть два решения этой проблемы:

а) просто избегайте этого (по соглашению избегайте использования одних и тех же имен в качестве параметров и полей).

б) использовать инструменты, которые выявляют такие проблемы и сообщают вам о них. Например, у findbugs есть явное правило, сообщающее вам о слежке. И, вероятно, IDE тоже можно предупредить об этом. См. здесь.

2

Учитывая тот факт, что это всего лишь «простое» задание… на мой взгляд, простая проверка «предела» общего класса была бы просто отличной.

13.08.2016
  • Мне интересно, как я не заметил такой мелочи .. Что ж, спасибо, что указали на это. Не могли бы вы прокомментировать вторую часть вопроса. 13.08.2016
  • используйте инструменты, которые выявляют такие проблемы и сообщают вам, не могли бы вы уточнить этот момент. Также, если для случая 2 возможны другие решения, сообщите мне об этом. 13.08.2016
  • Добавлены примеры для такого инструментария. 14.08.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..