Поток Java Callable Pool делает все это одновременно

Привет, у меня проблема с потоком. Я хочу использовать один метод для n потока, и я не знаю, как это сделать. сделайте это так: у меня есть список новых объектов, которые выглядят следующим образом: я создаю класс (1), который реализует интерфейс Callable. Я использую это, потому что вызываемый поток не возвращает void. Далее у меня есть список строк (url). Затем я создаю список объектов, которые выглядят как class (1). затем я создаю исполнителя, и я хочу сделать поток в моем списке объектов n-thread

public class UtlToImageConverter implements Callable<BufferedImage> {

    private String url;
    private static BufferedImage image;

    public UtlToImageConverter(String url) {
        this.url = url;
        getImgFromPath(url);
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        UtlToImageConverter.image = image;
    }

    public static BufferedImage getImgFromPath(String path){
        if(TestURLImage4.imgCache.get(path) != null){
            return TestURLImage4.imgCache.get(path);
        }
        else{
            URL url = null;
            try {
                url = new URL(path);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            try {
                image = ImageIO.read(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(TestURLImage4.imgCache.size());
            TestURLImage4.imgCache.put(path, image);
            return image;
        }
    }

    @Override
    public BufferedImage call() throws Exception {
        System.out.println("url  "  +url);
        getImgFromPath(url);
        System.out.println("url ok "  +url);
        return image;
    }

}

Далее я делаю это:

ArrayList<UtlToImageConverter> threadList = new ArrayList<>(); 
            for(String url : URLPathList){
                threadList.add(new UtlToImageConverter(url));
            }
            ExecutorService executor = Executors.newFixedThreadPool(10);

        try {
//          executor.invokeAll(threadList, 1000L, TimeUnit.SECONDS);
            executor.invokeAll(threadList);
//          executor.invokeAny(threadList);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
//      } catch (ExecutionException e) {
//          e.printStackTrace();
        }       

person Krzysztof Pokrywka    schedule 02.09.2016    source источник
comment
Хотя вы забыли задать вопрос, у вас, очевидно, есть две основные проблемы: (1) в вашем пуле потоков только один поток, вам нужно больше для параллельного выполнения задач, измените 1 на фактическое количество потоков, которое вы хотите использовать в вызове newFixedThreadPool(). (2) Вам нужно использовать invokeAll(), чтобы быть уверенным, что все ваши задачи выполнены и завершены; invokeAny() выполняет все задачи, но ожидает завершения только одной из них, а затем отменяет остальные.   -  person Andrew Lygin    schedule 02.09.2016
comment
@AndrewLygin Хорошо, я перехожу на этот ExecutorService executor = Executors.newFixedThreadPool (10); Но если у меня есть номер 1, 2 или 10, он работает так же   -  person Krzysztof Pokrywka    schedule 02.09.2016
comment
@AndrewLygin Изменено количество newFixedThreadPool, время не меняется   -  person Krzysztof Pokrywka    schedule 02.09.2016
comment
Это работает так же, потому что вы звоните ivokeAny(). Выполняет одну задачу и останавливается. Вам нужно invokeAll(). Но это не обязательно изменит время, он только выполнит больше работы, которая займет то же время или даже больше времени. Но, по крайней мере, все ваши изображения будут загружены. Теперь вы загружаете только одно изображение.   -  person Andrew Lygin    schedule 02.09.2016
comment
@AndrewLygin Я изменил это на: executor.invokeAll (threadList, 1000l, TimeUnit.MINUTES); Но это ничего не меняет   -  person Krzysztof Pokrywka    schedule 02.09.2016
comment
@AndrewLygin Если у меня сейчас 1 или 10 потоков, он работает так же   -  person Krzysztof Pokrywka    schedule 02.09.2016
comment
Что вы имеете в виду под тем же самым. Какие сообщения выводит программа? Сколько предметов у вас в URLPathList?   -  person Andrew Lygin    schedule 02.09.2016
comment
@AndrewLygin в URLPathList у меня 256 элементов, тогда как для e.x. 1 пул потоков этот процесс занимает 31 секунду, когда у меня 10 пулов потоков, процесс занимает 31 секунду. Я редактирую код сейчас Вы видите, что у меня есть   -  person Krzysztof Pokrywka    schedule 02.09.2016
comment
Вы видите URL-адрес сообщения ... и URL-адрес в порядке ...? Вы видите, что они работают параллельно? Попробуйте использовать System.out.println(String.format("%d: URL %s", Thread.currentThread().getId(), "abc")) вместо System.out.println("url " +url). Вы видите разные идентификаторы потоков?   -  person Andrew Lygin    schedule 02.09.2016
comment
Результат @AndrewLygin: 29: URL abc 30: URL abc 31: URL abc 38: URL abc 36: URL abc 34: URL abc 29: URL abc 33: URL abc 30: URL abc 31: URL abc 33: URL abc   -  person Krzysztof Pokrywka    schedule 02.09.2016


Ответы (1)


Проблема в том, что вы вызываете getImgFromPath() из конструктора UtlToImageConverter. Таким образом, все изображения загружаются в процессе создания экземпляра последовательно, прежде чем быть отправлены исполнителю. Исполнитель просто извлекает их из кеша, поэтому вы не видите разницы. Удалите вызов getImgFromPath() из конструктора и позвольте исполнителю выполнить фактическую загрузку.

person Andrew Lygin    schedule 02.09.2016
comment
не могли бы вы сказать мне, как это должно выглядеть. Потому что я не знаю, как я могу это сделать - person Krzysztof Pokrywka; 04.09.2016
comment
Просто удалите строку getImgFromPath(); из конструктора (это 8-я строка в вашем коде). - person Andrew Lygin; 04.09.2016
comment
Я делаю то, что вы сказали, я удаляю эту строку из конструктора, но если у меня есть 1 пул потоков или 10, 20 или 100, время все равно такое же - person Krzysztof Pokrywka; 05.09.2016
comment
Это странно, потому что этот код у меня работает. Может быть, веб-сервер, который обрабатывает ваши запросы, не может делать это параллельно? Все ли URL-адреса указывают на один и тот же сервер? - person Andrew Lygin; 05.09.2016
comment
Попробуйте загрузить в программу URL-адреса с разных веб-серверов и посмотрите, работает ли она. Я пробовал десять URL-адресов из разных сервисов и 1, 3 или 10 потоков. Разница была очевидна. - person Andrew Lygin; 05.09.2016
comment
Хорошо, это привет. Спасибо за помощь :-) - person Krzysztof Pokrywka; 06.09.2016