Лучшие практики для кэширования изображений, прочитанных из входного потока в Java - PullRequest
1 голос
/ 27 марта 2009

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

HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);

InputStream in = connection.getInputStream();
OutputStream out = resp.getOutputStream();

byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
  out.write(buf, 0, count);
}

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

Ответы [ 2 ]

2 голосов
/ 27 марта 2009

В некоторых ограниченных случаях может работать хеш-карта. Но вам нужно подумать о:

(1) Как вы собираетесь очищать кэшированные изображения из памяти, когда кэш заполнен (однако вы определяете это - возможно, какой-то максимальный объем памяти, который вы хотите выделить для кэширования). (2) Как вы собираетесь бороться с параллелизмом. (3) Соответственно, как вы будете иметь дело со случаем, когда клиент A запрашивает изображение, а затем клиент B запрашивает то же изображение, пока оно все еще загружается в кэш для клиента A.

Очень простое решение (1) может заключаться в том, чтобы всегда сохранять SoftReferences для данных изображения и позволить JVM позаботиться о принятии решения о том, когда их очищать (имейте в виду, что это может произойти произвольно, иногда в не зависящих от вас). В противном случае вам необходимо разработать какую-то политику (сначала - изображение, к которому обращались дольше всего назад, наименьшее / наибольшее изображение и т. Д., Изображение, которое понадобится больше всего времени для декодирования, если нам потребуется загрузить его снова и т. Д.) - только вы знаете свои данные и использование так что вы должны найти правильную политику.

Для (2) ConcurrentHashMap , как правило, поможет вам; Вы можете решить использовать явные блокировки и другие утилиты параллелизма в более изумительных случаях.

Для (3) довольно элегантное решение, предложенное Гетцем и его коллегами, заключается в угоне класса Future. На вашей карте вы сохраняете Future в кэшированном объекте (или в вашем объекте «записи в кэше»). Если запрашивающий объект обнаруживает, что Future уже добавлен на карту, он может вызвать get () и подождать, пока другой поток завершит кеширование данных. (Вы можете достичь аналогичного эффекта с явной блокировкой и условием, но Future берет на себя часть работы за вас.)

P.S. Я согласен с постером, который сказал, что вы, вероятно, хотите хранить изображения в их первоначальном кодированном виде. Но из вашего кода я предполагаю, что это было, вероятно, то, что вы намеревались все время.

2 голосов
/ 27 марта 2009

Если вы кэшируете только изображения, я бы рекомендовал хранить изображение в виде байтового массива, а не изображения. Использование imageio для чтения изображения приведет к распаковке изображений и займет намного больше места в памяти.

Класс WeekHashMap - это, вероятно, самый простой способ кэширования вещей, но у вас мало контроля над тем, как из него удаляются записи.

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