Пример кода для imgscalr AsyncScalr - PullRequest
3 голосов
/ 17 марта 2012

Может кто-нибудь поделиться примером кода imgscalr, используя AsyncScalr для изменения размера кода?Я пытаюсь использовать imgscalr (класс Scalr) для обработки изображений.Это хорошая и простая в использовании библиотека, однако, она выдает OutOfMemoryException слишком часто.Я надеюсь, что использование AsyncScalr решит мою проблему при низких нагрузках.

Ответы [ 2 ]

3 голосов
/ 19 марта 2012

Если вы знакомы с библиотеками Java Concurrent, использование класса AsyncScalr действительно просто;если вы не знакомы с новыми параллельными библиотеками, суть в следующем:

  1. Вызовите метод API, который выполняет некоторую работу в неизвестном месте в будущем;вызов метода возвращает Future , который оборачивает фактическую работу.
  2. Исходный вызов API фактически ставит работу в очередь;если он не занят, он, скорее всего, выполнит работу сразу, но если он занят и очередь огромна, работа может занять некоторое время (в этом случае «работа» - это масштабированиеimage).
  3. Вызывающий код (ваш код), который хочет получить результат, может продолжать работать до тех пор, пока Future.isDone () не вернет true, чтобы указать, что работа завершена ИЛИ вызывающий код можетпросто блокируйте, пока операция не будет выполнена, вызывая: Future.get () - этот метод возвращает результат работы, в данном случае BufferedImage, который представляет масштабированный результат.

Код буквально в итоге выглядит так:

// Block until result is done
BufferedImage result = AsyncScalr.resize(origImage, 125).get();

Разница между этим кодом и использованием класса Scalr напрямую заключается в том, что в многопоточных системах, если вы вызываете Scalr.resize () (или любой из операций с изображениями) из ВСЕХ ваших потоков, каждый из этих потоков начнет дорогостоящую операцию с изображениями, загружая ваш ЦП параллельной работой и замедляя систему доcrawl (отключение других процессов, запущенных на нем, таких как БД или веб-сервер).

Используя AsyncScalr класс , вы можете безопасно вызывать AsyncScalr.resize (или любую другую операцию) с любого номерапотоков и никогда не беспокоиться о том, чтобы загружать хост-систему работой; AsyncScalr.THREAD_COUNT определяет, сколько одновременных заданий может выполняться одновременно;Обычно вы хотите установить это число ядер на хост-машине или меньше количества ядер, если на хост-машине также размещены другие важные сервисы, такие как база данных или веб-сервер (чтобы вы не заглушали другиеобрабатывает, когда масштабирование занято).

Вы можете установить это значение потока в командной строке во время запуска приложения с помощью системного свойства "imgscalr.async.threadCount";по умолчанию это «2», но вы можете установить его на «1», если вы беспокоитесь о том, что в системе слишком мало памяти.

В качестве альтернативы, если у вас есть работа, которую может выполнять ваш поток, пока вы ждетеВ результате вы можете сделать что-то вроде этого, чтобы действительно эффективно использовать асинхронное программирование:

// Queue up the scaling operation (or any other op)
Future<BufferedImage> result = AsyncScalr.resize(origImage, 125);

/*
 * You can do other work here that doesn't need 'result', like making
 * DB calls, cleaning up temp files or anything else you might need to
 * do.
 */

// Now we are all done and need the resulting image, so we wait for it.
BufferedImage scaledImage = result.get();

// Do something with the image...

Если у вас было значительное количество других работ, которые вы могли бы выполнять, ожидая, пока изображениемасштабироваться, вы можете просто зациклить result.isDone() и продолжать работать, пока операция масштабирования не будет завершена;но если у вас есть только определенный / конкретный объем работы, не нужно зацикливаться на isDone, просто сделайте эту работу, затем вызовите Future.get(), чтобы получить результат (или заблокируйте его, пока он не будет готов).

Надеюсь, это поможет!

0 голосов
/ 29 июня 2015

Вот полезный метод, который планирует изменение размера изображения.Приятно то, что он возвращает ListenableFuture, что позволяет вам прикрепить обратный вызов, который выполняется после изменения размера изображения.

/**
 * Schedules the asynchronous resizing of an image.
 * <p>
 * Uses all available processors to do so.
 * 
 * @param pathToImage
 *            the path to the image we want to resize
 * @param quality
 *            the quality we want the output image to have. One of {@link Method}.
 * @param desiredSize
 *            the resulting image will not have a bigger height or width than this
 * @return
 *         a {@link ListenableFuture} of the resulting image. You can add a callback to it using {@link Futures#addCallback(ListenableFuture, FutureCallback)}
 * @throws IOException
 *             if the image at {@code pathToImage} couldn't be read
 */
public static ListenableFuture<BufferedImage> resize(String pathToImage, Method quality, int desiredSize) throws IOException {

    // Configure AsyncScalr to use all available processors for resizing the images
    String nrOfProcessors = String.valueOf(Runtime.getRuntime().availableProcessors());
    System.setProperty(AsyncScalr.THREAD_COUNT_PROPERTY_NAME, nrOfProcessors);

    BufferedImage image = ImageIO.read(new File(pathToImage));
    Future<BufferedImage> ordinaryFuture = AsyncScalr.resize(image, quality, desiredSize);
    ListenableFuture<BufferedImage> futureImage = JdkFutureAdapters.listenInPoolThread(ordinaryFuture);
    image.flush();
    return futureImage;
}

И вот как вы используетеresize:

ListenableFuture<BufferedImage> futureImage = resize("/path/to/img.png", Method.SPEED, 250);

Futures.addCallback(futureImage, new FutureCallback<BufferedImage>() {
  @Override
  public void onSuccess(BufferedImage result) {
          System.out.println("Your resized image is ready :-)");
  }
  @Override
  public void onFailure(Throwable t) {
          System.out.println("Couldn't resize image :-(");
  }
});

ListenableFuture и FutureCallback оба определены в библиотеке гуавы .

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