【问题标题】:How do you repeatedly call a Thread in Java?你如何在Java中重复调用一个线程?
【发布时间】:2009-03-15 22:18:12
【问题描述】:

我希望每 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();
}
}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    只需启动线程一次,使其循环,并在每次迭代时执行Thread.sleep(500L)。这可能比每 500 毫秒启动一个全新线程更有意义。如果可以避免,就没有理由产生相关费用。

    【讨论】:

    • 我觉得自己真的很蠢。 :)
    • 嗯,我记得我使用了一个while循环来让线程在另一个程序中继续运行。我不知道为什么我忘记了。 :)
    【解决方案2】:

    尝试使用 java util timer 或 ScheduledExecutorService,而不是使用 swing 计时器。摆动计时器共享一个预先存在的计时器线程,这可能导致冻结。

    来自java教程的推荐:

    一般来说,对于 GUI 相关的任务,我们建议使用 Swing 计时器而不是通用计时器,因为 Swing 计时器都共享相同的、预先存在的计时器线程,并且与 GUI 相关的任务会自动在事件调度线程上执行。但是,如果您不打算从计时器触摸 GUI,或者需要执行冗长的处理,则可以使用通用计时器

    【讨论】:

      【解决方案3】:

      如果您的 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() 停止重复执行任务。

      【讨论】:

        【解决方案4】:

        您需要在每个计时器操作上启动线程。调用线程的 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);
            }
        }
        

        【讨论】:

        • 如果我只希望一个下载器一次下载东西怎么办?
        • 然后我会让下载器在迭代之间休眠。您的 GUI 冻结的原因是线程从未启动...
        【解决方案5】:

        嗯,很可能你需要做的就是降低线程优先级,这样它就不会吃掉你所有的资源。

        【讨论】:

        • 它并不落后。它阻止 GUI 运行。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-10
        • 2021-10-26
        相关资源
        最近更新 更多