Java学习教程,从入门到精通,Java ConcurrentHashMap语法知识点及案例代码 ...

打印 上一主题 下一主题

主题 884|帖子 884|积分 2654

Java ConcurrentHashMap语法知识点及案例代码

ConcurrentHashMap 是 Java 中一个非常重要的线程安全的哈希表实现,它允许并发访问和修改,而且性能相对较好。以下是 ConcurrentHashMap 的语法知识点以及一个带有详细解释的示例代码。
语法知识点


  • 引入包
    1. import java.util.concurrent.ConcurrentHashMap;
    复制代码
  • 创建对象
    1. 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 来存储和管理线程安全的键值对。
  1. import java.util.concurrent.ConcurrentHashMap;
  2. import java.util.Map;public class ConcurrentHashMapExample {    public static void main(String[] args) {        // 创建一个ConcurrentHashMap实例        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
  3.         // 利用put方法添加元素        map.put("Apple", 1);        map.put("Banana", 2);        map.put("Orange", 3);        // 利用get方法获取元素        Integer value = map.get("Banana");
  4.         System.out.println("Value for 'Banana': " + value);        // 利用containsKey方法检查是否包含某个键        boolean containsKey = map.containsKey("Apple");
  5.         System.out.println("Map contains 'Apple': " + containsKey);        // 利用remove方法移除元素        map.remove("Orange");
  6.         // 利用size方法获取元素数量        int size = map.size();
  7.         System.out.println("Size of the map: " + size);        // 利用isEmpty方法检查是否为空        boolean isEmpty = map.isEmpty();
  8.         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());
  9.     }}
复制代码
代码解释


  • 创建 ConcurrentHashMap 实例
    1. ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
    复制代码
  • 添加元素
    1. map.put("Apple", 1);
    2. map.put("Banana", 2);
    3. map.put("Orange", 3);
    复制代码
  • 获取元素
    1. Integer value = map.get("Banana");
    复制代码
  • 检查是否包含某个键
    1. boolean containsKey = map.containsKey("Apple");
    复制代码
  • 移除元素
    1. map.remove("Orange");
    复制代码
  • 获取元素数量
    1. int size = map.size();
    复制代码
  • 检查是否为空
    1. boolean isEmpty = map.isEmpty();
    复制代码
  • 遍历全部元素
    1. map.forEach((key, value) -> {
    2.     System.out.println("Key: " + key + ", Value: " + value);
    3. });
    复制代码
  • 模拟并发访问

    • 界说了一个 Runnable 使命,每个使命会向 ConcurrentHashMap 中添加一些键值对。
    • 创建并启动两个线程来实行这个使命。
    • 利用 join 方法等待两个线程实行完毕。

  • 输出最终的元素数量
    1. System.out.println("Final size of the map after concurrent operations: " + map.size());
    复制代码
通过这些示例和解释,你应该可以或许把握 ConcurrentHashMap 的根本用法和并发特性。希望这些信息对你有资助!
以下是关于 ConcurrentHashMap 的几个具体案例,这些案例展示了在差别场景下怎样利用 ConcurrentHashMap 来实现线程安全的键值对存储和访问。
案例一:用户访问计数器

在这个案例中,我们利用 ConcurrentHashMap 来实现一个用户访问计数器,用于统计差别用户的访问次数。
  1. import java.util.concurrent.ConcurrentHashMap;
  2. 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 来实现一个简朴的缓存体系,用于存储和访问缓存数据。
  1. import java.util.concurrent.ConcurrentHashMap;
  2. 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 来实现一个简朴的使命分配体系,用于将使命分配给多个工作线程。
  1. import java.util.concurrent.ConcurrentHashMap;
  2. 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企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南七星之家

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表