Содержание
HashMap это очень мощная структура данных в Java. Мы используем его каждый день и почти во всех приложениях. Есть довольно много примеров, которые я написал ранее о том, как реализовать потокобезопасный кеш , как конвертировать Hashmap в Arraylist ?
Мы использовали Hashmap в обоих приведенных выше примерах, но это довольно простые случаи использования Hashmap. HashMap is a non-synchronized коллекционный класс.
Есть ли у вас какие-либо вопросы ниже?
- В чем разница между ConcurrentHashMap и Collections.synchronizedMap (Map)?
- В чем разница между ConcurrentHashMap и Collections.synchronizedMap (Map) с точки зрения производительности ?
- ConcurrentHashMap против Collections.synchronizedMap ()
- Популярные вопросы интервью HashMap и ConcurrentHashMap
В этом уроке мы рассмотрим все вышеперечисленные вопросы и причины why and how мы могли бы синхронизировать Hashmap?
Зачем?
Объект Map представляет собой ассоциативные контейнеры, в которых хранятся элементы, образованные комбинацией уникальной идентификации key и нанесенный на карту value , Если у вас есть приложение с высокой степенью параллелизма, в котором вы можете изменить или прочитать значение ключа в разных потоках, тогда идеально использовать Concurrent Hashmap. Лучшим примером является Producer Consumer, который обрабатывает одновременное чтение / запись.
Так что же означает поточно-ориентированная карта? Если multiple threads получить доступ к хеш-карте одновременно, и по крайней мере один из потоков изменяет карту структурно, он must be synchronized externally чтобы избежать противоречивого просмотра содержимого.
Как?
Есть два способа синхронизировать HashMap
- Метод Java Collections synchronizedMap ()
- Используйте ConcurrentHashMap
|
1
2
3
4
5
6
7
8
|
//Хеш-таблица
Карта < Строка , Строка > NormalMap знак равно новый Hashtable < String , Строка > ( ) ;
// synchronizedMap
synchronizedHashMap знак равно Коллекции . synchronizedMap ( новый HashMap < String , Строка > ( ) ) ;
// ConcurrentHashMap
ConcurrentHashMap знак равно новый ConcurrentHashMap < String , Строка > ( ) ;
|
ConcurrentHashMap
- Вы должны использовать ConcurrentHashMap, когда вам нужен очень высокий параллелизм в вашем проекте.
- Поток безопасен без синхронизации
whole map, - Чтение может происходить очень быстро, в то время как запись выполняется с блокировкой.
- На уровне объекта нет блокировки.
- Блокировка на более тонкой детализации на уровне сегмента хэш-карты.
- ConcurrentHashMap не создает
ConcurrentModificationExceptionесли один поток пытается изменить его, в то время как другой перебирает его. - ConcurrentHashMap использует множество блокировок.
SynchronizedHashMap
- Синхронизация на уровне объекта .
- Каждая операция чтения / записи должна получить блокировку.
- Блокировка всей коллекции — накладные расходы.
- По сути, это дает доступ только одному потоку ко всей карте и блокирует все остальные потоки.
- Это может вызвать раздор.
- SynchronizedHashMap возвращает
Iterator, который терпит неудачу при одновременной модификации.
Теперь давайте посмотрим на код
- Создать класс
CrunchifyConcurrentHashMapVsSynchronizedHashMap.java - Создать объект для каждого HashTable, SynchronizedMap и CrunchifyConcurrentHashMap
- Добавить и получить 500 тыс. Записей с карты
- Измерьте время начала и окончания и время отображения в миллисекундах
- Мы будем использовать ExecutorService для запуска
5 threadsв параллели
Вот код 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
пакет crunchify. ком . учебные пособия ;
Импортировать Java. Util. Коллекции ;
Импортировать Java. Util. HashMap ;
Импортировать Java. Util. Hashtable ;
Импортировать Java. Util. Карта ;
Импортировать Java. Util. одновременно. ConcurrentHashMap ;
Импортировать Java. Util. одновременно. ExecutorService ;
Импортировать Java. Util. одновременно. Исполнители ;
Импортировать Java. Util. одновременно. TimeUnit ;
/ **
* @author Crunchify.com
*
* /
общественности учебный класс CrunchifyConcurrentHashMapVsSynchronizedMap {
общественности окончательный статический ИНТ THREAD_POOL_SIZE знак равно 5 ;
общественности статический Карта < Строка , Целое число > crunchifyHashTableObject знак равно ноль ;
общественности статический Карта < Строка , Целое число > crunchifySynchronizedMapObject знак равно ноль ;
общественности статический Карта < Строка , Целое число > crunchifyConcurrentHashMapObject знак равно ноль ;
общественности статический недействительным main ( Строка [ ] аргументы ) бросает InterruptedException {
// Тест с Hashtable объектом
crunchifyHashTableObject знак равно новый Hashtable < String , Целое число > ( ) ;
crunchifyPerformTest ( crunchifyHashTableObject ) ;
// Тестирование с объектом synchronizedMap
crunchifySynchronizedMapObject знак равно Коллекции . synchronizedMap ( новый HashMap < String , Целое число > ( ) ) ;
crunchifyPerformTest ( crunchifySynchronizedMapObject ) ;
// Тест с объектом ConcurrentHashMap
crunchifyConcurrentHashMapObject знак равно новый ConcurrentHashMap < String , Целое число > ( ) ;
crunchifyPerformTest ( crunchifyConcurrentHashMapObject ) ;
}
общественности статический недействительным crunchifyPerformTest ( окончательный Карта < Строка , Целое число > crunchifyThreads ) бросает InterruptedException {
Система. вне. println ( «Тест начался для:» + crunchifyThreads . getClass ( ) ) ;
долго среднее время знак равно 0 ;
за ( int я знак равно 0 ; я < 5 ; я ++ ) {
долго начальное время знак равно Система. nanoTime ( ) ;
ExecutorService crunchifyExServer знак равно Исполнители . newFixedThreadPool (THREAD_POOL_SIZE);
за ( int J знак равно 0 ; J < THREAD_POOL_SIZE ; j ++ ) {
crunchifyExServer . выполнить ( новый Runnable ( ) {
@SuppressWarnings ( «не используется» )
@Override
общественности недействительным запустить ( ) {
за ( int я знак равно 0 ; я < 500000 ; я ++ ) {
целое число crunchifyRandomNumber знак равно ( int ) Математика ceil ( Math . random ( ) * 550000 ) ;
// Получить значение. Мы его нигде не используем
целое число crunchifyValue знак равно crunchifyThreads . get ( String . valueOf ( crunchifyRandomNumber ) ) ;
// положить значение
crunchifyThreads . put ( String . valueOf ( crunchifyRandomNumber ) , crunchifyRandomNumber ) ;
}
}
} ) ;
}
// Инициирует упорядоченное отключение, при котором выполняются ранее отправленные задачи, но новые задачи не принимаются. мольба
// не имеет никакого дополнительного эффекта, если он уже выключен.
// Этот метод не ожидает завершения выполнения ранее представленных задач. Используйте awaitTermination, чтобы сделать это.
crunchifyExServer . выключение ( ) ;
// Блокирует до тех пор, пока все задачи не завершат выполнение после запроса на выключение, или не истечет время ожидания, или текущий поток
// прерывается, в зависимости от того, что произойдет первым.
crunchifyExServer . awaitTermination ( Long . MAX_VALUE , TimeUnit . ДНИ ) ;
долго entTime знак равно Система. nanoTime ( ) ;
долго общее время знак равно ( entTime — startTime ) / 1000000L ;
среднее время + = totalTime ;
Система. вне. println ( 500K введено добавлено / получено в + общее время + мс ) ;
}
Система. вне. println ( «Для» + crunchifyThreads . getClass ( ) + среднее время + среднее время / 5 + ms / n ) ;
}
}
|
shutdown()означает, что служба исполнителя не принимает больше входящих задач.awaitTermination()вызывается после запроса на отключение.
И, следовательно, вам необходимо сначала закрыть serviceExecutor, а затем заблокировать и дождаться завершения потоков.
Eclipse Console Результат:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
Тест начался для : учебный класс Java. Util. Хеш-таблица
500K entried добавлено / извлекаться в 1832 Миз
500K entried добавлено / извлекаться в 1723 Миз
500K entried добавлено / извлекаться в 1782 Миз
500K entried добавлено / извлекаться в 1607 Миз
500K entried добавлено / извлекаться в 1851 Миз
За учебный класс Java. Util. Hashtable среднее время 1759 Миз
Тест начался для : учебный класс Java. Util. Коллекции $ SynchronizedMap
500K entried добавлено / извлекаться в 1923 Миз
500K entried добавлено / извлекаться в 2032 Миз
500K entried добавлено / извлекаться в 1621 Миз
500K entried добавлено / извлекаться в 1833 Миз
500K entried добавлено / извлекаться в 2048 Миз
За учебный класс Java. Util. Коллекции $ SynchronizedMap среднее время является 1891 Миз
Тест начался для : учебный класс Java. Util. одновременно. ConcurrentHashMap
500K entried добавлено / извлекаться в 1068 Миз
500K entried добавлено / извлекаться в 1029 Миз
500K entried добавлено / извлекаться в 1165 Миз
500K entried добавлено / извлекаться в 840 Миз
500K entried добавлено / извлекаться в 1017 Миз
За учебный класс Java. Util. одновременно. ConcurrentHashMap среднее время +1023 Миз
|
0.00 (0%) 0 votes







