Является ли использование ExecutorService внутри SwingWorker хорошей практикой? - PullRequest
6 голосов
/ 28 марта 2012

Рассмотрим следующий код:

        SwingWorker<Void, Void> sworker = new SwingWorker<Void, Void>() {

        @Override
        protected Void doInBackground() throws Exception {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            try {
                for (int j = 0; j < 5; j++) {
                    Callable<Object> worker = new MyCallableImpl();
                    Future<Object> future = executor.submit(worker); 
                    array[j] = future.get();
                }
            } catch (InterruptedException e) {
                // some code here
            } catch (ExecutionException e) {
                // some code here
            }
                // some code here
            executor.shutdown();
            return null;
        }

    };
    sworker.execute();

Как я уже сказал в заголовке: это хорошая практика для вызова ExecutorService внутри метода doInBackground () SwingWorker? Это работает для меня (JDK1.7), GUI не заблокирован, и несколько потоков из пула Executor работают в фоновом режиме, но все же у меня есть некоторые сомнения ...

Ответы [ 3 ]

2 голосов
/ 28 марта 2012

Для дальнейшего ответа мрэ.Это не имеет смысла, потому что ваше выполнение на самом деле является однопоточным.doInBackground отправит исполнителю и дождется завершения одной задачи, затем отправит другую.

Вы должны отправить тот же способ, но сохранить возвращенные Future s в каком-либо Списке, а затем войти в каждое из них после того, как все задачи были отправлены.

Я неdoInBackground должен представить эти задания асинхронно, как и mre.Если вы пытаетесь отправить несколько заданий и в каждый момент времени отправляете только N, вам определенно не следует делать это через SwingWorker.doInBackground.Использование ExectorService + SwingUtilities.invokeLater Я думаю, что это лучший способ.

И просто для выяснения любой путаницы, invokeLater следует использовать здесь только тогда, когда задача в ExecutorService завершена и все, что нужно сделать, это обновить компонент пользовательского интерфейса.

Редактировать: Примерчтобы ответить на ваш комментарий

protected Void doInBackground() throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    List<Future> futures = ...;
    try {
        for (int j = 0; j < 5; j++) {
            Callable<Object> worker = new MyCallableImpl();
            futures.add(executor.submit(new Callable<Object>(){
                 public Object call(){
                    //expensive time consuming operation
                    final String result = ...;//result from consuming operation
                    SwingUtilities.invokeLater(new Runnable(){
                        public void run(){
                             jLabel.setText(result);
                        }
                    });
                    return new Object();
                 }
            ));
        }
        for(Future<Object> f :futures)f.get();
        executor.shutdown();
    return null;
}

Обратите внимание, как invokeLater делается для простого обновления?Это не должно вызывать зависание вашего EDT.

2 голосов
/ 28 марта 2012
  • может выполнять экземпляр SwingWorkers от Executor

  • должен признать, что Executor не заботится о жизненном цикле SwingWorkers и наоборот

  • должен реализовать PropertyChangeListener для SwingWorker

  • например здесь

2 голосов
/ 28 марта 2012

Приведенный выше код не имеет особого смысла для меня.

Если целью здесь является обеспечение того, чтобы графический интерфейс оставался отзывчивым во время выполнения длительной задачи, то нет необходимости использовать ExecutorService, поскольку SwingWorker уже предоставляет этот механизм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...