Почему UnsupportedOperationException
?
Ваш класс WorkerThread
реализует интерфейс Callable
, а именно:
Задача, которая возвращаетрезультат и может вызвать исключение. Разработчики определяют один метод без аргументов с именем call
.
API, которые используют реализации Callable
, такие как ExecutorService#invokeAny(Collection)
, вызовут метод call
, который означает, что фактическая работа должна быть реализована внутри указанного call
метод. Однако ваш код выглядит следующим образом:
@Override
public String call() throws Exception {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
Вот почему вы получаете UnsupportedOperationException
, потому что это именно то, что запрограммировано для метода. Чтобы это исправить, вам нужно просто правильно реализовать метод. У вас также есть:
public void run() {
processCommand(start, end);
}
Что заставляет меня думать, что вы либо запутались между интерфейсами Runnable
и Callable
или классом WorkerThread
, используемым для реализации Runnable
, и вы забыли обновить кодполностью при переключении на Callable
. Предполагая, что processCommand
является фактической работой задачи, ваш метод call
должен выглядеть примерно так:
@Override
public String call() throws Exception {
processCommand(start, end);
return "I don't know what's supposed to be returned";
}
И вы можете удалить метод run
.
Ожидание завершения
Вы не должны вращаться в ожидании завершения ExecutorService
:
while (!executor.isTerminated()) {
}
Интерфейс предоставляет метод, который блокирует до завершения ExecutorService
, что обычно значительноболее дружественный к процессору: ExecutorService#awaitTermination(long,TimeUnit)
. Метод принимает значение тайм-аута, чтобы указать максимальное количество времени, которое поток должен блокировать в ожидании завершения. Если вы хотите подождать «навсегда», используйте действительно большое значение, например:
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
Избегайте необработанных типов
Я рекомендую прочитать Что такое необработанный тип ипочему бы нам не использовать его? . Интерфейс Callable
является общим, но в некоторых местах вы используете необработанный тип. Вместо:
public class WorkerThread implements Callable {...}
// and
Callable worker = new WorkerThread(...);
Вы должны иметь:
public class WorkerThread implements Callable<String> {...}
// and
Callable<String> worker = new WorkerThread<>(...);
Потоки пользовательского интерфейса
Обратите внимание, что у вас есть java.awt.Label
, который обновляется внутриprocessCommand
метод. Имейте в виду, что объекты UI обычно должны быть доступны только в потоке пользовательского интерфейса (например, Thread Dispatch Thread (EDT) в Swing). По крайней мере, так обстоит дело с Swing - я не уверен, является ли AWT поточно-ориентированным или нет. Тем не менее, я на самом деле не уверен, почему вы используете Label
, поскольку ни один из вашего кода не связан с графическим интерфейсом.