我想要一个线程每500毫秒在后台执行一次。为此,我扩展了一个Thread,实现了ActionListener并将我扩展的类放入Timer中。 Timer每500毫秒调用run()。但是,当这个线程从Internet下载东西时,我的整个Swing GUI都会冻结。我希望它在后台运行,而不会在等待IO完成时冻结GUI。我也是下载器,在我们等待500毫秒之前完成下载。
调用gogogo()来初始化整个过程:
public final class Downloader extends Thread implements ActionListener
{
public static void gogogo()
{
t= new Downloader();
new Timer(500, (ActionListener) t).start();
}
public void run()
{
doStuff(); //the code that i want repeatedly called
}
public void actionPerformed(ActionEvent e)
{
run();
}
}
答案 0 :(得分:8)
只需启动一次线程,使其循环,并在每次迭代时执行Thread.sleep(500L)
。每隔500毫秒启动一个全新的线程可能更有意义。如果可以避免,就没有理由承担相关费用。
答案 1 :(得分:1)
尝试使用java util计时器或ScheduledExecutorService,而不是使用swing计时器。摆动计时器共享预先存在的计时器线程,这可能导致冻结。
来自java教程的建议:
通常,我们建议使用Swing计时器而不是通用计时器来处理与GUI相关的任务,因为Swing计时器都共享相同的预先存在的计时器线程,并且GUI相关任务会在事件派发线程上自动执行。但是,如果您不打算从计时器触摸GUI,或者需要执行冗长的处理,则可以使用通用计时器
答案 2 :(得分:1)
如果您的GUI冻结,那么您的长度任务(doStuff)可能正在事件调度线程上运行。虽然它占用了那个线程,但其他动作却无法使用它。
如果您尝试重复运行任务,那么使用TimerTask类可能会更好
public class Downloader extends TimerTask {
public void run() {
doStuff();
}
}
... elsewhere ...
Timer myTimer = new Timer();
public void gogogo() {
myTimer.scheduleAtFixedRate(new Downloader(), 0, 500);
}
这有点不同,因为您的任务将被安排为每500毫秒运行一次,而不是延迟500毫秒。完成后,只需使用myTimer.cancel()来停止重复执行任务。
答案 3 :(得分:0)
您需要在每个计时器操作上启动线程。调用线程的run()方法不会启动线程。
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
最好为actionlistener使用匿名类。请原谅我的java语法,但我还没有验证它......
new Timer(500,
new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
}).start();
或没有计时器......
public static void gogogo()
{
t= new Downloader();
t.start();
}
public void run()
{
while(true){
doStuff(); //the code that i want repeatedly called
Thread.sleep(500);
}
}
答案 4 :(得分:-1)
嗯,你很可能只需减少线程优先级,所以它不会占用你所有的资源。