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

Как сделать секундомер в виде потока на Java?


Я пытаюсь реализовать секундомер, аналогичный тому, который можно найти по адресу Есть ли секундомер? в Java?, но как Thread.

Мой класс SecondsCounter реализует Runnable, и вызов его метода start создаст поток как локальную переменную.

Может показаться, что этот поток конфликтует с первой строкой в ​​методе run: this.runningTime = System.currentTimeMillis(); ...потому что условие while (this.runningTime < this.endTime) никогда не нарушается (бесконечный цикл). ..

То есть неправильно иметь класс, который одновременно реализует Runnable и также содержит его Thread?



Вот класс с основным методом:

public class MultithreadingTest {

    public static void main(String[] args) {
        int totalSeconds = 5;
        SecondsPrinter printer = new SecondsPrinter(totalSeconds);
        printer.startPrinting();
    }
} // end of class


...класс секундного принтера:

public class SecondsPrinter {

    // composition here:
    private SecondsCounter clock;

    public SecondsPrinter(int totalSeconds) {
        this.clock = new SecondsCounter(totalSeconds);
    }

    public void startPrinting() {
        this.clock.start();
        while (this.clock.isRunning()) {

            // this is incorrectly always printing the maximum seconds value:
            System.out.println(this.clock.getCurrentSecond());
        }
    }
} // end of class


...и класс счетчика секунд:

public class SecondsCounter implements Runnable {

    private int totalSeconds, currentSecond;
    private long startTime, runningTime, endTime;
    private Thread thread;

    public SecondsCounter(int totalSeconds) {
        this.totalSeconds = totalSeconds;
    }

    public int getCurrentSecond() {
        return this.currentSecond;
    }

    @Override
    public void run() {
        this.runningTime = System.currentTimeMillis();

        // this is an infinite loop, but it shouldn't be:
        while (this.runningTime < this.endTime) {
            this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
        }

        // this code is never reached:
        this.stop();
    }

    public void start() {
        this.startTime = System.currentTimeMillis();
        this.runningTime = this.startTime;
        this.endTime = this.startTime + (this.totalSeconds * 1000);

        // multithreading here:
        this.thread = new Thread(this);
        this.thread.start();
    }

    public boolean isRunning() {
        return this.thread.isAlive();
    }

    public void stop() {
        this.thread.interrupt();
        this.thread = null;
    }
} // end of class
09.11.2013

  • Это много кода. Я бы подумал, как вы могли бы упростить его, чтобы делать то, что вы хотите. 09.11.2013
  • @PeterLawrey - Хм, я мог бы исключить переменную startTime в классе SecondsCounter и, возможно, передать миллисекунды вместо секунд его конструктору, чтобы упростить некоторые операции преобразования единиц измерения. Вместо этого я мог бы просто использовать java.util.Timer, но я делаю это по-своему, просто чтобы поэкспериментировать с потоками. В остальном я не замечаю каких-либо проблем с разделением проблем или нарушений DRY. Что вы могли бы предложить? 09.11.2013

Ответы:


1

На самом деле, это должен быть бесконечный цикл. Посмотрите на свою петлю.

while (this.runningTime < this.endTime) {
    this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
}

Условие говорит, что он будет зацикливаться, пока runningTime < endTime. Где обновляется runningTime? Если вы добавите что-то подобное в цикл, он должен работать:

public void run() {
    this.runningTime = System.currentTimeMillis();

    // no longer an infinite loop
    while (this.runningTime < this.endTime) {
        this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
        this.runningTime = System.currentTimeMillis();
    }

    // this code is now reached.
    this.stop();
}

Вы даже можете объединить это (или вообще удалить переменную runningTime):

public void run() {
    while ((this.runningTime = System.currentTimeMillis()) < this.endTime) {
        this.currentSecond = (int)(this.endTime - this.runningTime) / 1000;
    }

    this.stop();
}
09.11.2013
  • О, ха, я полностью пропустил это, дох! Теперь он работает правильно, спасибо @Quincunx за помощь. 09.11.2013
  • Интересно, я не знал, что вы можете установить и затем использовать значение в качестве условия цикла while, спасибо @Quincunx! Это только работает, когда параметр заключен в круглые скобки, например: while( ( this.runningTime = System.currentTimeMillis() ) < this.endTime) { ... он не компилируется без закрывающих круглых скобок из-за проблем с приоритетом операций с <. 09.11.2013
  • @IanCampbell Это работает, потому что оператор присваивания также возвращает присваиваемое им значение. Он работает только со скобками, потому что операторы присваивания имеют самый низкий приоритет операций, поэтому без круглых скобок мы получаем this.runningTime = (System.currentTimeMillis() < this.endTime);. Хороший улов в скобках. 09.11.2013
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге 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 , и использованием..

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