Фоновое задание работает, не затрагивая остальную часть графического интерфейса - PullRequest
3 голосов
/ 21 июля 2011

Прошу помощи по поводу общего подхода.

Я написал некоторый код Java, чтобы проверить мой почтовый ящик на наличие непрочитанных писем при нажатии кнопки.

Теперь я хочу, чтобы этот код постоянно работал в фоновом режиме и проверял мой почтовый ящик каждые 2 минуты.

Плохая идея:

while(true)
{
checkMails();
Thread.sleep(120000);
}

Остальная часть графического интерфейса, очевидно, зависает, поэтому, наверное, должно произойти какое-то волшебство с потоками.

Как это могло быть реализовано?

Ответы [ 6 ]

4 голосов
/ 21 июля 2011

Либо используйте javax.swing.Timer, либо SwingWorker, хотя последнее в этом сценарии немного избыточно.


Если эта задача не изменяет какие-либо компоненты Swing, то почему бы просто не создать отдельный поток, как таковой

Thread t = new Thread(new Runnable(){
    @Override
    public void run(){
        while(!Thread.currentThread().isInterrupted()){
            //do stuff

            try{
                Thread.sleep(120000);
            }catch(InterruptedException e){
                Thread.currentThread().interrupt();
            }
        }
    }
});
t.start();

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

2 голосов
/ 21 июля 2011

Почему бы вам не создать отдельный поток, который будет обрабатывать checkMails(), и выполнить то действие, которое у вас уже есть. Просто будьте осторожны при обновлении графического интерфейса.

    Thread thread = new Thread(new Runnable() {
        public void run() {

            while (true) {
                checkMails();
                Thread.sleep(120000);
            }
        }
    });

edit: Может быть, вам стоит добавить проверку где-то в том случае, если вы хотите прекратить проверку новой почты (по какой-либо причине). Также вы должны позвонить thread.start();

1 голос
/ 21 июля 2011

Вам нужно использовать многопоточность, чтобы решить эту проблему.Потоки похожи на многозадачность.

Thread t = new Thread(){
    public void run(){
        //do job
    }
}
t.start(); //starts the thread

Чтобы завершить поток, вам понадобится какое-то условие остановки

public boolean run = false;
Thread t = new Thread(){
    public void run(){
        while(run)
            //do job
    }
}
public void startThread(){
    t.start(); //starts the thread
}

См. Также:

Thread.stop() убьет поток, но это очень плохо.Например, предположим, что вы записываете в массив

for(int i = 0; i < myAr.length; i++)
    myAr[i] = getStuff(i);

И в i = 5 вызывается Thread.stop().Теперь ваша программа думает, что все хорошо, хотя на самом деле это не так!

Чтобы убить поток, установите run на false.run - это boolean, который я показал во втором примере.Другой вариант - создать подкласс Thread (не только в методах переопределения строк) и создать метод halt() (stop является окончательным).halt() установит для run значение false.run все еще будет глобальным boolean.

Вот пример этого.

public class MyThread extends Thread {
    public boolean run = true;
    public void run(){
        run = true;
        while(run)
            doStuff();
    }
    public void halt(){
        run = false;
    }
}

Вы должны быть осторожны, чтобы два потока не модифицировали один и тот же объект одновременноэто было бы похоже на превращение объекта в генератор случайных чисел: /

Теперь, когда вы получили силу потоков, используйте ее с умом, во благо, а не во зло!Иди вперед и будь осторожен.

1 голос
/ 21 июля 2011

Используйте javax.swing.Timer. Примерно так:

int delay = 120000;
ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        checkMails();
    }
};
new Timer(delay, taskPerformer).start();
0 голосов
/ 21 июля 2011

Несколько идей:

1) Создайте java.util.Timer, который периодически запускается, проверяя почтовый ящик на наличие сообщений и обновляя графический интерфейс с помощью SwingUtilities#invokeLater;

2) Создайте таймер (java.util.Timer или javax.swing.Timer), который планирует javax.swing.SwingWorker для проверки почтового ящика и обновления графического интерфейса.

3) Создать Thread, который проверяет почтовый ящик, обновляет графический интерфейс с помощью SwingUtilities#invokeLater и некоторое время спит;

Я бы использовал 1 или 2, потому что вы можете просто остановить таймеры, если вам когда-нибудь понадобится отменить задачу.

0 голосов
/ 21 июля 2011

Очевидно, что вам нужно использовать EDT , если вам нужно обновить интерфейс после завершения метода checkMails ().

И вы ищете асинхронный (другой синхронный) способ.

Конечно, вы ищете SwingUtilities.html # invokeLater (java.lang.Runnable)

Насколько мне известно, это правильный способ сделать фоновое задание для Swing.

Runnable checkMail = new Runnable() {
    public void run() {
        while(true) {
            checkMails();
            Thread.sleep(120000); //but this is very naive approach to use sleep, consider using timer ;)
        }
    }
};

SwingUtilities.invokeLater(checkMail);

invokeLater (Runnable doRun): вызывает асинхронное выполнение doRun.run () в потоке диспетчеризации событий AWT.

и

invokeAndWait (Runnable doRun): заставляет doRun.run () выполняться синхронно в потоке диспетчеризации событий AWT.

...