3

我正在寻求有关一般方法的帮助。

我已经编写了一些 java 代码来检查我的邮箱是否有按钮单击上的未读邮件。

现在我希望这段代码在后台永久运行,每 2 分钟检查一次我的邮箱。

馊主意:

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

图形界面的其余部分显然冻结了,所以我想线程必须发生一些魔法。

这怎么可能实现?

4

6 回答 6

4

要么使用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();

请务必注意,您可能希望使用 aboolean来确保线程只创建一次,因为每次单击按钮时都有可能产生一个新线程,这可能不是您想要的。

于 2011-07-21T14:04:34.610 回答
2

您为什么不生成一个单独的线程来处理checkMails()并执行您已经拥有的操作。更新 GUI 时要小心。

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

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

编辑:如果您想停止检查新邮件(无论出于何种原因),也许您应该在某处添加检查。你也得打电话thread.start();

于 2011-07-21T14:03:31.923 回答
1

使用javax.swing.Timer. 像这样的东西:

int delay = 120000;
ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        checkMails();
    }
};
new Timer(delay, taskPerformer).start();
于 2011-07-21T14:04:33.627 回答
1

你需要使用线程来解决这个问题。线程就像多任务处理。

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()被调用。现在您的程序认为一切都很好,但实际上并非如此!

要终止线程,请设置runfalse. runboolean我在第二个例子中展示的。另一种选择是创建一个子类Thread(不仅仅是在线覆盖方法)并创建一个方法halt()stop是最终的)。halt()将设置run为假。run仍将是一个全球性的boolean.

这是一个例子。

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

您需要注意两个线程不会同时修改同一个对象,这就像将一个对象变成一个随机数生成器:/

既然您已经获得了线的力量,请明智地使用它,为善而不是为恶!继续前进并保持线程安全。

于 2011-07-21T14:10:45.733 回答
0

一些想法:

1)创建一个java.util.Timer定期触发,检查邮箱中的消息并使用更新GUI SwingUtilities#invokeLater

2) 创建一个计时器(java.util.Timerjavax.swing.Timer),用于安排 ajavax.swing.SwingWorker来检查邮箱和更新 GUI。

3)创建一个Thread检查邮箱,更新GUI使用SwingUtilities#invokeLater并休眠一段时间;

我会使用 1 或 2,因为如果您需要取消任务,您可以停止计时器。

于 2011-07-21T15:06:17.917 回答
-1

显然,如果在完成 checkMails() 方法后需要更新 UI,则需要使用EDT 。

而您正在寻找异步(另一种是同步)方式。

当然,您正在寻找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 事件调度线程上同步执行。

于 2011-07-21T14:21:22.900 回答