Java ConcurrentHashMap语法知识点及案例代码
ConcurrentHashMap 是 Java 中一个非常重要的线程安全的哈希表实现,它允许并发访问和修改,而且性能相对较好。以下是 ConcurrentHashMap 的语法知识点以及一个带有详细解释的示例代码。
语法知识点
- 引入包:
- import java.util.concurrent.ConcurrentHashMap;
复制代码 - 创建对象:
- ConcurrentHashMap<KeyType, ValueType> map = new ConcurrentHashMap<>();
复制代码 - 根本方法:
- put(K key, V value):将一个键值对放入映射中。
- get(Object key):根据键获取值。
- remove(Object key):根据键移除键值对。
- containsKey(Object key):检查映射中是否包含指定的键。
- size():返回映射中的键值对数量。
- isEmpty():检查映射是否为空。
- forEach(BiConsumer<? super K, ? super V> action):对映射中的每个键值对实行给定的操纵。
- 并发特性:
- ConcurrentHashMap 利用分段锁(Segment Locks)或更当代的 CAS(Compare-And-Swap)操纵来实现并发性,从而允很多个线程同时读取和写入。
- 它的内部实现复杂,但对外提供了简便的接口。
示例代码
以下是一个简朴的示例代码,展示了怎样利用 ConcurrentHashMap 来存储和管理线程安全的键值对。
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.Map;public class ConcurrentHashMapExample { public static void main(String[] args) { // 创建一个ConcurrentHashMap实例 ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
- // 利用put方法添加元素 map.put("Apple", 1); map.put("Banana", 2); map.put("Orange", 3); // 利用get方法获取元素 Integer value = map.get("Banana");
- System.out.println("Value for 'Banana': " + value); // 利用containsKey方法检查是否包含某个键 boolean containsKey = map.containsKey("Apple");
- System.out.println("Map contains 'Apple': " + containsKey); // 利用remove方法移除元素 map.remove("Orange");
- // 利用size方法获取元素数量 int size = map.size();
- System.out.println("Size of the map: " + size); // 利用isEmpty方法检查是否为空 boolean isEmpty = map.isEmpty();
- System.out.println("Is the map empty? " + isEmpty); // 利用forEach方法遍历全部元素 System.out.println("Elements in the map:"); map.forEach((key, value) -> { System.out.println("Key: " + key + ", Value: " + value); }); // 模拟并发访问 Runnable task = () -> { for (int i = 0; i < 10; i++) { String key = "Key" + i; map.put(key, i); System.out.println(Thread.currentThread().getName() + " added " + key + " with value " + i); } }; // 创建并启动多个线程 Thread thread1 = new Thread(task, "Thread-1"); Thread thread2 = new Thread(task, "Thread-2"); thread1.start(); thread2.start(); try { // 等待线程竣事 thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } // 最终的元素数量(大概大于初始数量,由于多线程添加) System.out.println("Final size of the map after concurrent operations: " + map.size());
- }}
复制代码 代码解释
- 创建 ConcurrentHashMap 实例:
- ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
复制代码 - 添加元素:
- map.put("Apple", 1);
- map.put("Banana", 2);
- map.put("Orange", 3);
复制代码 - 获取元素:
- Integer value = map.get("Banana");
复制代码 - 检查是否包含某个键:
- boolean containsKey = map.containsKey("Apple");
复制代码 - 移除元素:
- 获取元素数量:
- 检查是否为空:
- boolean isEmpty = map.isEmpty();
复制代码 - 遍历全部元素:
- map.forEach((key, value) -> {
- System.out.println("Key: " + key + ", Value: " + value);
- });
复制代码 - 模拟并发访问:
- 界说了一个 Runnable 使命,每个使命会向 ConcurrentHashMap 中添加一些键值对。
- 创建并启动两个线程来实行这个使命。
- 利用 join 方法等待两个线程实行完毕。
- 输出最终的元素数量:
- System.out.println("Final size of the map after concurrent operations: " + map.size());
复制代码 通过这些示例和解释,你应该可以或许把握 ConcurrentHashMap 的根本用法和并发特性。希望这些信息对你有资助!
以下是关于 ConcurrentHashMap 的几个具体案例,这些案例展示了在差别场景下怎样利用 ConcurrentHashMap 来实现线程安全的键值对存储和访问。
案例一:用户访问计数器
在这个案例中,我们利用 ConcurrentHashMap 来实现一个用户访问计数器,用于统计差别用户的访问次数。
- import java.util.concurrent.ConcurrentHashMap;
- public class UserVisitCounter { // 利用ConcurrentHashMap存储用户访问次数 private ConcurrentHashMap<String, Integer> userCounts = new ConcurrentHashMap<>(); // 用户访问时调用此方法增长计数 public void visit(String userId) { // 利用compute方法实现线程安全的计数更新 userCounts.compute(userId, (key, value) -> (value == null) ? 1 : value + 1); } // 获取用户的访问次数 public int getCount(String userId) { // 利用getOrDefault方法获取访问次数,假如未找到则返回0 return userCounts.getOrDefault(userId, 0); } public static void main(String[] args) { UserVisitCounter counter = new UserVisitCounter(); // 模拟多线程用户访问 Runnable task = () -> { for (int i = 0; i < 10; i++) { String userId = "User" + (int) (Math.random() * 100); counter.visit(userId); System.out.println(Thread.currentThread().getName() + " visited " + userId + ", total count: " + counter.getCount(userId)); } }; // 创建并启动多个线程 for (int i = 0; i < 5; i++) { new Thread(task).start(); } }}
复制代码 案例二:缓存体系
在这个案例中,我们利用 ConcurrentHashMap 来实现一个简朴的缓存体系,用于存储和访问缓存数据。
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.TimeUnit;public class SimpleCache<K, V> { // 利用ConcurrentHashMap存储缓存数据 private ConcurrentHashMap<K, CacheEntry<K, V>> cache = new ConcurrentHashMap<>(); // 缓存项,包含值和过期时间 private static class CacheEntry<K, V> { final V value; final long expireTime; CacheEntry(V value, long expireTime) { this.value = value; this.expireTime = expireTime; } boolean isExpired() { return System.currentTimeMillis() > expireTime; } } // 添加缓存项,指定过期时间 public void put(K key, V value, long expireTime, TimeUnit timeUnit) { long expireTimeMillis = System.currentTimeMillis() + timeUnit.toMillis(expireTime); cache.put(key, new CacheEntry<>(value, expireTimeMillis)); } // 获取缓存项的值,假如缓存项已过期,则返回null public V get(K key) { CacheEntry<K, V> entry = cache.get(key); if (entry != null && !entry.isExpired()) { return entry.value; } else { // 缓存项已过期或不存在,从缓存中移除(可选) cache.remove(key); return null; } } public static void main(String[] args) throws InterruptedException { SimpleCache<String, String> cache = new SimpleCache<>(); // 添加缓存项,设置过期时间为5秒 cache.put("key1", "value1", 5, TimeUnit.SECONDS); // 访问缓存项 System.out.println("key1: " + cache.get("key1")); // 输出: value1 // 等待6秒,使缓存项过期 Thread.sleep(6000); // 再次访问缓存项,此时应返回null System.out.println("key1 after expiration: " + cache.get("key1")); // 输出: null }}
复制代码 案例三:使命分配体系
在这个案例中,我们利用 ConcurrentHashMap 来实现一个简朴的使命分配体系,用于将使命分配给多个工作线程。
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TaskDistributor { // 利用ConcurrentHashMap存储使命和对应的处理线程 private ConcurrentHashMap<String, String> taskAssignments = new ConcurrentHashMap<>(); // 添加使命并分配处理线程 public void assignTask(String taskId, String workerId) { taskAssignments.put(taskId, workerId); } // 获取使命的处理线程 public String getWorkerForTask(String taskId) { return taskAssignments.get(taskId); } public static void main(String[] args) { TaskDistributor distributor = new TaskDistributor(); // 创建工作线程池 ExecutorService executorService = Executors.newFixedThreadPool(3); // 模拟添加使命并分配处理线程 for (int i = 0; i < 10; i++) { String taskId = "Task" + i; String workerId = "Worker" + (i % 3); // 简朴地利用取模运算分配工作线程 distributor.assignTask(taskId, workerId); } // 工作线程实行使命 Runnable taskExecution = () -> { for (String taskId : distributor.taskAssignments.keySet()) { String workerId = distributor.getWorkerForTask(taskId); if (workerId.equals(Thread.currentThread().getName().substring(7))) { System.out.println(Thread.currentThread().getName() + " is processing " + taskId); } } }; // 启动工作线程 for (int i = 0; i < 3; i++) { executorService.execute(new Thread(taskExecution, "Worker" + i)); } // 关闭线程池(等待全部使命完成) executorService.shutdown(); }}
复制代码 留意:在第三个案例中,由于线程池和使命分配是并发进行的,因此实际的使命分配和处理大概会有所差别。这里的示例重要是为了展示怎样利用 ConcurrentHashMap 来存储和访问使命分配信息。在实际应用中,大概需要更复杂的逻辑来处理使命分配和线程同步。
这些案例展示了 ConcurrentHashMap 在差别场景下的应用,包括用户访问计数器、缓存体系和使命分配体系。通过利用 ConcurrentHashMap,我们可以实现线程安全的键值对存储和访问,从而满意高并发场景下的需求。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |