powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / HashMap & Threads
9 сообщений из 9, страница 1 из 1
HashMap & Threads
    #38295230
Lisichkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Предыстория:
Имеется процедура, которая загружает изображения из Интернета и потом, помещает их в базу данных. Процедура вызывается из разных нитей с разными параметрами.
Порой бывают ситуации, когда разные потоки пытаются одновременно скачать одинаковые изображения. Хотелось бы избежать двойной работы.
Естественно перед загрузкой проверяется наличие изображения в базе данных. Но поскольку процесс загрузки может занимать значительное время – то получается, что одновременно несколько нитей убеждаются, что изображения нет, и одновременно начинают его загружать. (Блокировать на уровне записи в базе данных я не могу – sqlite поддерживает блокировку на уровне файла базы).
Я написал класс регулирующий очередь загрузки изображений – класс блокирует повторную загрузку идентичного изображения. "Идентичность" изображения обусловлена равенством двух переменных: uid(long) и name(string).
Сначала я реализовал класс с помощью ConcurrentHashMap. Но потом, передумал и сделал с помощью обычного HashMap и synchronized.
Я поступил так, потому что в очереди может находится только один элемент с ключом (uid+name) – Set, поэтому в момент вставки элемента нужна полная блокировка всей очереди.
Покритикуйте мое решение.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
public class LoadImageQueue {

	class QueueItem {
		final long uid;
		final String name;
		
		QueueItem (long uid, String name) {
			this.uid = uid;
			this.name = name;
		}
		@Override	
		public boolean equals(Object o)	{
			QueueItem item = (QueueItem)o;  
			return uid==item.uid && name.equals(item.name);
		}		
		@Override	
		public int hashCode() {
			final String s = uid + name;
			return	s.hashCode();
		}		
	}
	
	//private ConcurrentHashMap<ImageItem, Lock> mQueue = new ConcurrentHashMap<ImageItem, Lock>();
	private HashMap<QueueItem, Lock> mQueue = new HashMap<QueueItem, Lock>();
	
	public QueueItem acquireLock(long uid, String name) {
		Lock lock;
		boolean getlock = false;
		final QueueItem item = new QueueItem(uid, name);
		synchronized (mQueue) {
			lock = mQueue.get(item);
			if (lock==null) {
				lock = new ReentrantLock();
				lock.lock();
				mQueue.put(item, lock);
				getlock = true;
			} else
				getlock = lock.tryLock();
		}
		if (!getlock)		
			lock.lock();
		return	item;
	}

	public void releaseLock(QueueItem item) {
		Lock lock;
		synchronized (mQueue) {
			lock = mQueue.remove(item);
		}
		if (lock==null)
        	throw new RuntimeException("release not acquire Lock");
		lock.unlock();
		lock = null;
	}
	
}
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295269
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LisichkinСначала я реализовал класс с помощью ConcurrentHashMap. Но потом, передумал и сделал с помощью обычного HashMap и synchronized.
Я поступил так, потому что в очереди может находится только один элемент с ключом (uid+name) – Set, поэтому в момент вставки элемента нужна полная блокировка всей очереди.Не очень, всё-таки, понятно, почему не устроили ConcurrentMap , ConcurrentHashMap с готовым атомарным putIfAbsent?
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295274
zalexaka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lisichkin,
Lock lock; — локальная переменная и это основной косяк, на вскидку. )
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295282
zalexaka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lisichkin,

Упс, сорри. Навскидку промазал)
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295295
Lisichkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
	private HashMap<QueueItem, Lock> mQueue = new HashMap<QueueItem, Lock>();

	public QueueItem acquireLock(long uid, String name) {
		final QueueItem item = new QueueItem(uid, name);
		Lock lock = mQueue.get(item);
		if (lock==null) {
			// Другая нить может успеть ранее вставить запись в очередь с налогичным uid+name
			lock = new ReentrantLock();
			lock.lock();
			mQueue.put(item, lock);
		} else
			lock.lock();
		return	item;
	}



или

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
	// Не кошерно - возможно лишнее создание ReentrantLock 
	public QueueItem acquireLock(long uid, String name) {
		final QueueItem item = new QueueItem(uid, name);
		lock = new ReentrantLock();
		// putIfAbsent атомарная операция? Не возможна ли ситуация когда в очереди возникнут два объекта с одним uid+name?
		lock = mQueue.putIfAbsent(item, lock);
		lock.lock();
		return	item;
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295304
Lisichkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чуть-чуть себя поправлю:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
	public QueueItem acquireLock(long uid, String name) {
		final QueueItem item = new QueueItem(uid, name);
		// Возможно лишнее создание ReentrantLock 
		// putIfAbsent атомарная операция? Не возможна ли ситуация когда в очереди возникнут два объекта с одним uid+name?
		Lock lock = mQueue.putIfAbsent(item,  new ReentrantLock());
		lock.lock();
		return	item;
	}
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295328
Lisichkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения в двух предыдущих постах mQueue - ConcurrentHashMap

Код: java
1.
ConcurrentHashMap<ImageItem, Lock> mQueue = new ConcurrentHashMap<ImageItem, Lock>();
...
Рейтинг: 0 / 0
HashMap & Threads
    #38295406
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если все, что нужно сделать, это гарантировать, что действие загрузки выполняется только один раз, то в таком сценарии создавать лок для каждой картинки смысла мало. Проще воспользоваться решением на основе названного выше ConcurrentHashMap + FutureTask.
...
Рейтинг: 0 / 0
HashMap & Threads
    #38296572
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lisichkin // putIfAbsent атомарная операция?Вы, мопвашуять, по ссылкам ходили, велосипедостроитель?
Это, конечно, если подчёркнутого слова "атомарный" вам недостаточно.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / HashMap & Threads
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]