Тайм-аут задачи с помощью Java SwingWorker - PullRequest
6 голосов
/ 01 марта 2010

Я пытаюсь реализовать класс SwingWorker в моем приложении.Есть ли способ установить промежуток времени, после которого SwingWorker «останавливается»?Я думал, что, возможно, выбрасываю исключение OutOfTime, которое я могу поймать, а затем разобратьсяЯ просто не уверен, как это реализовать.

Спасибо за вашу помощь!

Ответы [ 4 ]

4 голосов
/ 01 марта 2010

Почему бы не встроить вашу задачу в Runnable, перенести ее в новый однопоточный ExecutorService , а затем выполнить get() для результирующего Future с соответствующим временем ожидания. Это даст вам функциональность тайм-аута, так как get() вызовет исключение, если задание не будет выполнено вовремя.

1 голос
/ 06 августа 2010

Внутренний класс 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 <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);
}

}

1 голос
/ 01 марта 2010

Краткий ответ: «это сложно», в зависимости от ваших требований. Я настоятельно рекомендую прочитать Параллелизм Java на практике .

Основное, что вы можете сделать, это (а) убедиться, что ваш SwingWorker's Runnable дружественен к прерываниям, и (б) установить таймер (или использовать блокирующий вызов get (), упомянутый Брайаном) для отмены вашего будущего.

0 голосов
/ 05 ноября 2012

По какой-то конкретной причине не используется SwingWorker. get (long, java.util.concurrent.TimeUnit) ? Это вызовет исключение TimeoutException, которое вы можете легко обработать в вашем приложении.

...