преобразование в ScheduledThreadPoolExecutor

Я все еще новичок в Java, поэтому я мало что узнал о потоках и параллелизме. Однако я хотел бы иметь возможность использовать ScheduledThreadPoolExecutor в качестве таймера из-за проблем, с которыми я сталкиваюсь с java.util.Timer и TimerTask. Я чрезвычайно заинтересован в создании тем и знаю, что узнаю о них через несколько недель. Однако, если возможно, может ли кто-нибудь дать мне простой пример того, как преобразовать мою текущую мини-тестовую программу с использованием util.timer в использование ScheduledThreadPoolExecutor?

Я хотел бы завершить этот пример как можно скорее, поэтому у меня не так много времени на изучение потоков — как бы мне этого ни хотелось. Сказав это, пожалуйста, включите все, что вы считаете важным, что новичок Java должен знать в отношении ScheduledThreadPoolExecutor.

Пример программы

Я сделал небольшой пример, чтобы представить проблему, с которой я сталкиваюсь в более крупной программе. Что должна делать эта программа, так это позволять пользователю нажимать кнопку для запуска счетчика. Затем пользователь должен иметь возможность останавливать и перезапускать счетчик, когда захочет. В более крупной программе жизненно важно, чтобы этот счетчик оставался равным, поэтому я использовал метод scheduleAtFixRate(). Также важно, чтобы начальная задержка всегда была одинаковой (в данном случае 0). Проблема (как я уверен, вы увидите) заключается в том, что после отмены таймера его нельзя перезапустить — я надеюсь, что ScheduledThreadPoolExecutor решит эту проблему.

код:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.TimerTask;
import java.util.Timer;

public class Tester extends JFrame {
    JButton push = new JButton("Push");
    static JTextArea textOut = new JTextArea();
    Timer timer = new Timer();
    boolean pushed = false;
    static int i = 1;

    public Tester() {
        super();
        add(push, BorderLayout.NORTH);
        add(textOut);
        push.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!pushed) {
                    timer.scheduleAtFixedRate(new Task(), 0, 1000);
                    pushed = true;
                } else {
                    timer.cancel();
                    pushed = false;
                }
            }
        });
    }

    static class Task extends TimerTask {
        public void run() {
            textOut.setText("" + i++);
        }
    }

    public static void main(String[] args) {
        Tester a = new Tester();
        a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        a.pack();
        a.setVisible(true);
    }
}

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


person Saad Attieh    schedule 14.01.2013    source источник
comment
Я чувствую, что вы просите SO написать код для вас... под тонко завуалированной маской желания изучить потоки, я хотел бы завершить этот пример как можно скорее, поэтому у меня не так много времени, чтобы изучать потоки - неважно сколько бы я хотел.   -  person Alex DiCarlo    schedule 14.01.2013
comment
Обычно обучающий пример не содержит слов о том, что это важно и тому подобное.   -  person SJuan76    schedule 14.01.2013
comment
Надеюсь, никто так не думает. Я увлечен программированием и изучаю его в университете. Если бы я хотел, чтобы люди написали мою программу, я бы поместил реальный код в пример, а не пример быстрого теста, который я сделал.   -  person Saad Attieh    schedule 14.01.2013
comment
Я бы поместил в пример реальный код, а не пример быстрого теста, который я сделал Профессионал никогда не поместит реальный код, а вместо этого опубликует пример быстрого теста, иллюстрирующий его/ее проблему. Я никогда не видел, чтобы учащиеся вставляли такие слова, как Я хотел бы закончить этот пример как можно скорее или это жизненно важно.   -  person Guillaume Polet    schedule 14.01.2013
comment
Извините, и под жизненно важным я имел в виду, что мне нужна программа, чтобы делать то, что я написал. У меня каникулы, которые заканчиваются через несколько дней, и когда я вернусь в университет, у меня будет гораздо меньше времени на эксперименты с программами, которые я делаю сейчас. Вместо этого я буду писать то, что назначено, поэтому я использую это более спокойное время, чтобы улучшить свои знания в Java. Вот почему я хотел бы закончить программы, которые я сейчас пишу, как можно скорее, прежде чем я вернусь.   -  person Saad Attieh    schedule 14.01.2013
comment
Прошу прощения, если вам это покажется неправдоподобным, но спасибо за любую поддержку.   -  person Saad Attieh    schedule 14.01.2013
comment
если вам все еще интересно, что я имею в виду под жизненно важным, это просто то, что моя фактическая программа включает использование секундомера, и, как я уже упоминал, задержка должна быть минимальной, иначе она выйдет из синхронизации с другой функцией (не единственным классом в программе). это время отслеживания).   -  person Saad Attieh    schedule 14.01.2013


Ответы (1)


Заменять

Timer timer = new Timer();

с

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

и

class Task extends TimerTask

с

class Task implements Runnable

и

timer.scheduleAtFixedRate(new Task(), 0, 1000);

с

service.scheduleAtFixedRate(new Task(), 0, 1000, TimeUnit.MILLISECONDS);

Кстати, вы не должны пытаться обновить графический интерфейс в другом потоке. Вместо этого вам нужно добавить задачу в поток GUI Swing для выполнения задачи.

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            textOut.setText("" + i++);
        }
    });
person Peter Lawrey    schedule 14.01.2013
comment
Тем не менее, это продолжает добавлять мертвые потоки. Я получаю pool-##-thread-1, и они никогда не убираются. Я что-то упускаю? - person kmort; 09.12.2014
comment
@kmort Я предполагаю, что вы не выполняете shutdown(), когда закончите. - person Peter Lawrey; 09.12.2014
comment
Неа. Я этого не делал. Я не совсем уверен, как это сделать, поскольку я запускаю это в windowClosing() в диалоговом окне, которое исчезает сразу после того, как я планирую Runnable. Это плохо? (Я новичок в Java...) - person kmort; 10.12.2014
comment
@kmort это неплохо, однако вам нужно решить, когда вам это больше не нужно. Вы можете отключить вызов задачи (), если не хотите, чтобы она запускалась снова. - person Peter Lawrey; 10.12.2014
comment
Хорошо, теперь я понял. Я просто передаю ссылку на ScheduledExecutorService service в Runnable и вызываю service.shutdown() по завершении. Спасибо, Питер. Ваше здоровье. - person kmort; 10.12.2014