后台工作运行而不影响其余的gui

时间:2011-07-21 14:02:00

标签: java multithreading user-interface event-dispatch-thread

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

我已经编写了一些java代码,用于在buttonclick上查看我的邮箱中的未读邮件。

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

糟糕的主意:

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

图形界面的其余部分显然会冻结,所以我猜想必须在线程中发挥一些魔力。

怎么能实现呢?

6 个答案:

答案 0 :(得分:4)

使用javax.swing.TimerSwingWorker,虽然后者在这种情况下有点矫枉过正。


如果此任务不修改任何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来确保线程只创建一次,因为每次点击按钮都会产生一个新线程的可能性,这可能不是你想要什么。

答案 1 :(得分:2)

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

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

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

编辑:也许您应该在想要停止检查新邮件的情况下(无论出于何种原因)在某处添加支票。你也得打电话给thread.start();

答案 2 :(得分:1)

使用javax.swing.Timer。像这样:

int delay = 120000;
ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        checkMails();
    }
};
new Timer(delay, taskPerformer).start();

答案 3 :(得分: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 = 5Thread.stop()被调用。现在你的程序认为一切都很好,事实上,它不是!

要杀死该主题,请将run设置为falserun是我在第二个例子中展示的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;
    }
}

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

现在你已经获得了线程的力量,明智地使用它,为了善恶而不是邪恶!走吧,保持线程安全。

答案 4 :(得分:0)

一些想法:

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

2)创建一个计时器(java.util.Timerjavax.swing.Timer),计划javax.swing.SwingWorker以检查邮箱并更新GUI。

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

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

答案 5 :(得分:-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事件派发线程上同步执行。