2010-03-01 8 views
6

Tôi đang cố triển khai lớp SwingWorker trong ứng dụng của mình. Có cách nào để thiết lập một khoảng thời gian mà sau đó, các SwingWorker "lần ra"? Tôi đã nghĩ rằng có thể ném một ngoại lệ OutOfTime mà tôi có thể bắt và xử lý. Tôi chỉ không chắc chắn làm thế nào để thực hiện nó.Hết giờ một nhiệm vụ với SwingWorker của Java

Cảm ơn sự giúp đỡ của bạn!

Trả lời

4

Tại sao không nhúng tác vụ của bạn trong Runnable, hãy thả nó vào một đơn mới ExecutorService và sau đó thực hiện get() trên kết quả Future với thời gian chờ phù hợp. Điều đó sẽ cung cấp cho bạn chức năng thời gian chờ của bạn, vì get() sẽ ném một ngoại lệ nếu công việc không hoàn thành kịp thời.

+0

Ngoài ra: chỉ cần gọi get() với thời gian chờ sẽ vẫn để công việc (có lẽ đắt tiền) được thực hiện sau này. Nhiệm vụ cũng cần phải được hủy bỏ (và được viết theo cách hủy bỏ nó thực sự hoạt động) – Sbodd

+0

Bạn có thể ngắt() công việc của bạn thông qua phương thức Future.cancel() –

+0

(tạo ra một ThreadInterruptedException, tôi nghĩ) –

1

Câu trả lời ngắn gọn là "thật khó", tùy thuộc vào yêu cầu của bạn là gì. Tôi khuyên bạn nên đọc số Java Concurrency In Practice. Điều cơ bản bạn có thể làm là (a) đảm bảo RunWable của SwingWorker của bạn là gián đoạn thân thiện, và (b) thiết lập một Timer (hoặc sử dụng chặn get() gọi Brian đề cập) để hủy bỏ tương lai của bạn.

1

Lớp MySwingWorker bên trong cũng có thể làm những gì bạn cần:

package com.misc; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.Callable; 
import java.util.concurrent.FutureTask; 
import java.util.concurrent.TimeUnit; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class FutureStuffGUI extends JFrame { 
/** 
* Provides a variant of SwingWorker which operates with a timeout. 
* 
* @param <T> 
*/ 
private static abstract class MySwingWorker<T> { 

    private T result; 
    private Exception raised; 

    /** 
    * Constructor. 
    * 
    * @param timeout 
    * @param timeUnit 
    */ 
    public MySwingWorker(final long timeout, final TimeUnit timeUnit) { 
     result = null; 
     raised = null; 

     System.out.println(Thread.currentThread().getName() + " starting"); 
     final FutureTask<T> future = new FutureTask<T>(new Callable<T>() { 
      public T call() throws Exception { 
       System.out.println(Thread.currentThread().getName() + " running"); 
       T result = doInBackground(); 
       return result; 
      } 
     }); 
     System.out.println(Thread.currentThread().getName() + " future: " + future); 
     final Thread runner = new Thread(null, future, "FutureThread"); 
     Thread watcher = new Thread(null, new Runnable() { 

      @Override 
      public void run() { 
       runner.start(); 
       try { 
        result = future.get(timeout, timeUnit); 
       } catch (Exception ex) { 
        raised = ex; 
       } 
       SwingUtilities.invokeLater(new Runnable() { 

        @Override 
        public void run() { 
         assert SwingUtilities.isEventDispatchThread(); 
         done(); 
        } 
       }); 
      } 
     }, "WatcherThread"); 
     watcher.start(); 
    } 

    /** 
    * Implement this method as the long-running background task. 
    * 
    * @return 
    * @throws Exception 
    */ 
    abstract protected T doInBackground() throws Exception; 

    /** 
    * This method is invoked from the UI Event Dispatch Thread on completion or timeout. 
    */ 
    abstract protected void done(); 

    /** 
    * This method should be invoked by the implementation of done() to retrieve 
    * the result. 
    * 
    * @return 
    * @throws Exception 
    */ 
    protected T get() throws Exception { 
     assert SwingUtilities.isEventDispatchThread(); 
     if (raised != null) { 
      throw raised; 
     } else { 
      return result; 
     } 
    } 
} 

public FutureStuffGUI() { 
    super("Hello"); 
    init_components(); 
} 

private void init_components() { 
    JPanel panel = new JPanel(); 
    JButton button = new JButton("Press"); 
    panel.add(button); 
    add(panel); 
    pack(); 

    button.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      new MySwingWorker<String>(5, TimeUnit.SECONDS) { 

       @Override 
       protected String doInBackground() throws InterruptedException { 
        assert !SwingUtilities.isEventDispatchThread(); 
        System.out.println(Thread.currentThread().getName() + " doInBackground"); 
//      if (true) { throw new RuntimeException("Blow up"); } 
        Thread.sleep(6 * 1000); 
        return "Hello world!"; 
       } 

       @Override 
       protected void done() { 
        assert SwingUtilities.isEventDispatchThread(); 
        String result; 
        try { 
         result = get(); 
         System.out.println(Thread.currentThread().getName() + " done; result: " + result); 
        } catch (Exception ex) { 
         System.out.println(Thread.currentThread().getName() + " done; errored:"); 
         ex.printStackTrace(); 
        } 
       } 
      }; 
     }; 
    }); 
} 

public static void main(String[] args) { 
    FutureStuffGUI ui = new FutureStuffGUI(); 
    ui.setVisible(true); 
} 

}

+0

Thực hiện xong () sẽ luôn luôn nắm bắt 'java.util.concurrent.TimeoutException' ở đó. Điều đó có chủ ý không? – DejanLekic