Как исправить исключение concurrent.ExecutionException, вызванное: java.lang.UnsupportedOperationException - PullRequest
0 голосов
/ 15 октября 2019

Я опубликовал вопрос о грубом форсировании CodeReview , и хороший эксперт помог мне, предложив использовать многопоточность для повышения скорости моей программы. Код, который он дал, был хорош, улучшил скорость, но все еще был медленным для меня, поэтому я пошел больше исследовать многопоточность и нашел хорошие статьи и примеры . Я скопировал один пример, который я понял, и сделал несколько изменений, чтобы соответствовать моим потребностям. Код работает отлично, пока я не прочитал подробно о многопоточности и наткнулся на invokeAny (), я пытался реализовать его и, таким образом, начало моей головной боли по какой-то неизвестной причине, из-за которой я получаю ошибки. Я просто хочу иметь возможность получить первое задание, которое находит разрешенный идентификатор с помощью invokeAny, поскольку программа работает быстро.

Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: Not supported yet.
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at java.base/java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:199)
at java.base/java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:220)
at pait.SiimpleeThreadPool.main(SiimpleeThreadPool.java:31)
Caused by: java.lang.UnsupportedOperationException: Not supported yet.
at pait.WorkerThread.call(WorkerThread.java:73)
at pait.WorkerThread.call(WorkerThread.java:15)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.awt.Label;
import java.util.Random;
import java.util.concurrent.Callable;
public class SimpleThreadPool {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        int s = 135000000;
        int e = 200000000;
        List<Callable<String>> callList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Callable worker = new WorkerThread("" + i, s, e);
            callList.add(worker);
            s = s + 15520000;
        }
        String result = executor.invokeAny(callList);
        System.out.println(result);
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }

}

public class WorkerThread implements Callable {

    private final  String command;
    private final int start;
    private final int end;
    private final Label lb = new Label();

    public WorkerThread(String s, int start, int end) {
        this.command = s;
        this.start = start;
        this.end = end;
    }

    public void run() {
        processCommand(start, end);

    }

    private void processCommand(int start, int end) {
        for (int i = start; i < end; i++) {
            Random rand= new Random(i);
            long pair = rand.nextInt();
            if (pair == 739619665) {
                System.out.println(start + "     " + end + "        Executing Task inside : " + Thread.currentThread().getName());
                System.out.println(i);
                lb.setText("Stop");
                break;
            }
        }
    }

    ;

    @Override
    public String call() throws Exception {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public String toString() {
        return this.command;
    }

}

1 Ответ

1 голос
/ 15 октября 2019

Почему 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, поскольку ни один из вашего кода не связан с графическим интерфейсом.

...