使用Java的SwingWorker超时完成任务

我正在尝试在我的应用程序中实现SwingWorker类。 有没有办法设置一段时间,之后,SwingWorker“超时”? 我在想,可能会抛出一个OutOfTimeexception,我可以捕获然后再处理。 我只是不确定如何实现它。

感谢你的帮助!

为什么不将您的任务嵌入Runnable中,将其放入新的单线程ExecutorService中 ,然后在生成的Future上执行get()并使用适当的超时。 这将为您提供超时function,因为如果作业未及时完成, get()将抛出exception。

简短的回答是“很难”,取决于您的要求。 我强烈建议阅读Java Concurrency In Practice 。

你可以做的基本事情是(a)确保你的SwingWorker的Runnable是中断友好的,并且(b)设置一个Timer(或使用Brian提到的阻塞get()调用来取消你的Future。

内部类MySwingWorker可能会满足您的需求:

 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  */ private static abstract class MySwingWorker { 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 future = new FutureTask(new Callable() { 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(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); } 

}

不使用SwingWorker的任何特殊原因。 get(long,java.util.concurrent.TimeUnit) ? 它将抛出您可以在应用程序中轻松处理的TimeoutException。