2016-08-21 11 views
2

ScheduleAtFixedRateメソッドを使用する場合、ScheduledExecutorServiceを実装するScheduledThreadPoolExecutorは一度SwingWorkerクラスを実行しているようです。元のコードはちょっと長いので、私は以下の同じ結果をもたらす新しいコードを作った。ScheduledThreadPoolExecutorは一度だけSwingworkerを実行します

import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

public class ScheduledThreadPoolExecutorTest extends SwingWorker<Void, Void>{ 
    @Override 
    protected Void doInBackground() { 
     System.out.println("Yay!"); 
     return null; 
    } 

    @Override 
    protected void done() { 
     try { 
      get(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
     System.out.println("Woohoo!"); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 
       executor.scheduleAtFixedRate(new ScheduledThreadPoolExecutorTest(), 0, 30, TimeUnit.MILLISECONDS); 
      } 
     }); 
    } 
} 

これは、結果が得られます。

Yay! 
Woohoo! 

はなぜScheduledThreadPoolExecutorのは一度だけSwingWorkerのを実行していますか?そして、コードに示されているように30ミリ秒ごとにSwingWorkerを実行させるにはどうすればよいですか?

答えて

3

SwingWorkerのはdoInBackground()方法でそのAPI部当たり、Runnableインタフェースを実装しないが:

注この方法は、一度だけ実行されます。

、その内run()方法を繰り返し実行するかもしれないので、doInBackground()は一度だけ実行されます。それだけでなく、run()メソッドはSwingWorker内でfinalとマークされているので、doInBackgroundを複数回呼び出すようにオーバーライドすることはできません。

もっと良い解決策は、SwingWorkerを使うのではなく、もっと単純なRunnable派生クラスです。

+0

したがって、doInBackground()はクラスごとに1回だけ呼び出され、そのクラスのインスタンスごとには1回しか呼び出されません。また、Swingオブジェクトを使用しているので、 'repaint()'を呼び出す必要があるので、SwingWorkerを絶対に使用する必要がある場合はどうしたらいいでしょうか(当然のことながら、元のコードには表示されません)。 – ICanCYou

+0

@ ICanCYou:これはインスタンスごとに1回呼び出されますが、インスタンスは1つしか作成されません。 –

+0

@ICanCYou:SwingUtilieisを使用して、必要に応じて複数のSwingWorkersを作成したり、イベントスレッドにSwing呼び出しをキューイングすることもできます。イベントスレッドで 'repaint()'を呼び出す必要はないことに注意してください。 –

2

SwingWorkerはRunnableを拡張しますが、FutureTaskを使用して計算を実行します。 javadocツールから

ある
A cancellable asynchronous computation. This class provides a base 
implementation of {@link Future}, with methods to start and cancel 
a computation, query to see if the computation is complete, and 
retrieve the result of the computation. The result can only be 
retrieved when the computation has completed; the {@code get} 
methods will block if the computation has not yet completed. Once 
the computation has completed, the computation cannot be restarted 
or cancelled (unless the computation is invoked using 
{@link #runAndReset}). 

、FutureTaskあなたは再びそれを実行しようとした場合、それは単純に戻ります、一度だけ実行されます。

public void run() { 
    if (state != NEW || 
     !UNSAFE.compareAndSwapObject(this, runnerOffset, 
            null, Thread.currentThread())) 
     return; 
    try { 
     Callable<V> c = callable; 
     if (c != null && state == NEW) { 
      V result; 
      boolean ran; 
      try { 
       result = c.call(); 
       ran = true; 
      } catch (Throwable ex) { 
       result = null; 
       ran = false; 
       setException(ex); 
      } 
      if (ran) 
       set(result); 
     } 
    } finally { 
     // runner must be non-null until state is settled to 
     // prevent concurrent calls to run() 
     runner = null; 
     // state must be re-read after nulling runner to prevent 
     // leaked interrupts 
     int s = state; 
     if (s >= INTERRUPTING) 
      handlePossibleCancellationInterrupt(s); 
    } 
} 
関連する問題