11

コンソールアプリケーション用のGUIを実装していますが、指定した時間間隔でいくつかのアクション(たとえば、XMLファイルの解析)を実行する必要があります。これらのアクションによってアプリケーションが応答しなくなることがないように、SwingWorkerと一緒にjavax.swing.Timerを使用することにしました。

私はこのようにタイマーを実装しました:

public class DataUpdateTimer extends Timer {

    private String dataFlowControllerXML = null;
    private DataUpdateWorker dataUpdateWorker = null;

    public class DataUpdateWorker extends SwingWorker {

        private String dataFlowControllerXML = null;

        DataUpdateWorker(String dataFlowControllerXML) {
            super();
            this.dataFlowControllerXML = dataFlowControllerXML;
        }

        @Override
        protected Boolean doInBackground() throws Exception {

            Thread.sleep(300);
            return Boolean.TRUE;
        }

    }

    public class DataUpdateIntervalListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            DataUpdateTimer timer = (DataUpdateTimer)e.getSource();
            DataUpdateWorker dataUpdateWorker = timer.getDataUpdateWorker();

            if (dataUpdateWorker != null)
                if (dataUpdateWorker.isDone()) {
                    Boolean updateResult = Boolean.FALSE;
                    try {
                        updateResult = (Boolean)dataUpdateWorker.get();
                    } catch (InterruptedException ex) {

                    } catch (ExecutionException ex) {

                    }

                    dataUpdateWorker = null;
                }

            // Creating new worker thread here
            if (dataUpdateWorker == null) {
                timer.dataUpdateWorker = new DataUpdateWorker(timer.dataFlowControllerXML);

                // Starting a new worker thread for parsing Data Flow Controller's XML
                timer.dataUpdateWorker.execute();
                return;
            }
        }
    }

    DataUpdateTimer(Integer dataUpdateInterval, String dataFlowControllerXML) {

        super(dataUpdateInterval.intValue(), null);
        this.dataFlowControllerXML = dataFlowControllerXML;
        addActionListener(new DataUpdateIntervalListener());
    }

    @Override
    public void stop() {
        super.stop();
        if (dataUpdateWorker != null) {
            if (!dataUpdateWorker.isDone() || !dataUpdateWorker.isCancelled())
                dataUpdateWorker.cancel(true);
        }
    }
}

...そしてそれを次のように使用します:

new DataUpdateTimer(1000, dataFlowControllerXML).start();

すべてが私が望むように機能します。タイマーは新しいSwingWorkerインスタンスを作成し、それを実行します。ワーカーが完了すると、新しいワーカーが作成されて実行されます。

私が混乱しているのは、ワーカーのスレッドが完了した後も、Netbeansのデバッグウィンドウ(たとえば、SwingWorker-pool-3-thread-1)またはWindowsタスクマネージャー(実行中のスレッドは、スレッドが完了した後も減少しません)。SwingWorkerスレッドの数は10に制限されていますが、それらを実行すると恥ずかしい思いをします。

単純なスレッドの使用の場合:

Thread th = new Thread(new Runnable() {

    public void run() {
        int a = 0;
    }
});
th.start();

このスレッドは実行後に自動的に消えます。

このSwingWorkerの動作は正常ですか?

4

1 に答える 1

11

はい、これは正常です。スレッドの名前が示すように、スイングワーカーのモデル(バックグラウンド)アクションはスレッドプールに委任されています。作業が完了すると、スレッドはプールに戻され、別のワーカーが使用できるようになります。これにより、コストがかかる可能性のあるスレッドの作成/破棄のオーバーヘッドがなくなります。

ちなみに、バックグラウンドスレッドは永遠に固執することはありません。ソースを見ると、次のようになりSwingWorkerます。

//from SwingWorker.java (c) Sun Microsystems/Oracle 2009
executorService =
            new ThreadPoolExecutor(1, MAX_WORKER_THREADS,
                                   10L, TimeUnit.MINUTES,
                                   new LinkedBlockingQueue<Runnable>(),
                                   threadFactory);

これは、スレッドが10分間アイドル状態になった後に停止することを示しています。

于 2011-03-01T16:43:54.883 に答える