簡體   English   中英

與可能長時間運行的后台任務結合使用的擺動計時器

[英]Swing Timer in Conjunction with Possible Long-running Background Task

我需要重復執行一個既影響GUI相關對象又影響非GUI相關對象的任務。 一個警告是,如果在觸發下一個計時器事件時上一個任務尚未完成,則不應執行任何操作。 我最初的想法是將SwingTimer與javax.swing.SwingWorker對象結合使用。 常規設置如下所示。

class
{
    timer = new Timer(speed, this);
    timer.start(); 

    public void actionPerformed(ActionEvent e) 
    {
        SwingWorker worker = new SwingWorker() {
            @Override
            public ImageIcon[] doInBackground() {
                // potential long running task
            }

            @Override
            public void done() {
                // update GUI on event dispatch thread when complete
            }
    }
}

我看到這種方法的一些潛在問題是:

1)如果一個工作程序在計時器觸發下一個ActionEvent之前尚未完成,則多個SwingWorkers將處於活動狀態。

2)SwingWorker只能執行一次,因此保留對worker的引用並重用(不是?)可行的選擇。

有沒有更好的方法來實現這一目標?

您是否看過使用簡單的Java計時器和ReadWriteLock來確定計時器再次觸發時任務是否正在運行? 在這種情況下,您可以退出該特定迭代,然后等待下一個迭代。

為什么要使用計時器? 使“工作人員”始終保持運行會更簡單,只要任務花費的時間很少,就可以通過sleep()暫停。 您仍然可以使用類似以下的內容在事件分發線程中更新內容:

Thread background = new Thread(new Runnable() {
  public void run() {
    while ( ! stopRequested ) {
       long start = System.currentTimeMillis();
       // do task
       long elapsed = start - System.currentTimeMillis();

       SwingUtilities.invokeLater(new Runnable() { 
          public void run() { 
             // update UI
          }
       });
       if (elapsed < tickTime) {
          Thread.sleep(tickTime - elapsed);
       }
    }
  }
}.start();

對於(1), ScheduledThreadPoolExecutor上的scheduleAtFixedRate()方法可能很有用。 從javadocs:

如果此任務的任何執行花費的時間超過其周期,則后續執行可能會開始得較晚,但不會同時執行。

對於(2),看起來您可以定義SwingWorker的子類並為每次迭代構造該子類的新實例,而不是實例化匿名子類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM