конвертиране в 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);

BTW Не трябва да се опитвате да актуализирате GUI в друга нишка. Вместо това трябва да добавите задача към Swing GUI Thread, за да изпълните задачата

    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