2010-03-01 18 views
6

ile bir görev zaman aşımı Uygulamam içinde bir SwingWorker sınıfı uygulamaya çalışıyorum. SwingWorker'ın "zaman aşımına uğradığı" zamanın uzunluğunu belirlemenin bir yolu var mı? Yakalayabildiğim ve sonra başa çıkabileceğim bir OutOfTime istisnası atmayı düşünüyorum. Bunu nasıl uygulayacağından emin değilim.Java'nın SwingWorker

Yardımlarınız için teşekkürler!

cevap

4

Neden Runnable içinde görevinizi gömmek değil, içine bırakın yeni tek iş parçacıklı ExecutorService ve sonra uygun bir zaman aşımı ile sonuçlanan Future bir get() gerçekleştirin. Bu, zaman aşımı işlevlerinizi size verir, çünkü işin zamanında tamamlanmaması durumunda get() bir istisna atar.

+0

Ayrıca: sadece bir zaman aşımı ile get() çağırmak daha sonra yapılacak (muhtemelen pahalı) iş bırakacaktır. Görev de iptal edilmek zorundadır (ve aslında çalışmayı iptal edecek şekilde yazılır) – Sbodd

+0

Çalışmanızı bir Future.cancel() yöntemi –

+0

(threadInterruptedException oluşturur) ile kesebilirsiniz (bence) –

1

Gereksinimlerinize bağlı olarak kısa cevap “zor” dur. Java Concurrency In Practice'u okumanızı tavsiye ederim.

Yapabileceğiniz en temel şey, (a) SwingWorker'ın Runnable'ınızın interrupt dostu olduğundan emin olmak ve (b) bir Timer (veya bahsi geçen Brian'ın bloke edilen get() çağrısını kullanarak Geleceğinizi iptal etmek) olacaktır.

1

iç sınıf MySwingWorker iyi ne gerek yapabilirsiniz: SwingWorker kullanmayan için

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

Yapılan uygulama () her zaman orada java.util.concurrent.TimeoutException 'yakalayacak. Bu kasıtlı mı? – DejanLekic