CyStack logo
  • Sản phẩm & Dịch vụ
  • Giải pháp
  • Bảng giá
  • Công ty
  • Tài liệu
Vi

vi

Mục lục

Trang chủBlogConcurrentHashMap trong J...
Java

ConcurrentHashMap trong Java: Tính năng và ứng dụng thực tế

3 phút đọc18/09/2025
CyStack Author
Chris Pham

Technical Writer

0 lượt xem
Reading Time: 3 minutes

ConcurrentHashMap trong Java là một class trong Concurrency Collection. Nó là một triển khai của hash table (bảng băm), hỗ trợ truy xuất và cập nhật đồng thời. ConcurrentHashMap được dùng trong môi trường đa luồng để tránh lỗi ConcurrentModificationException.

ConcurrentHashMap trong Java

ConcurrentHashMap

Nếu ta cố gắng chỉnh sửa một collection trong khi đang duyệt qua nó, ta sẽ gặp lỗi ConcurrentModificationException. Java 1.5 đã bổ sung các class Concurrent trong gói java.util.concurrent để giải quyết vấn đề này.

ConcurrentHashMap là một triển khai của Map, cho phép chúng ta chỉnh sửa Map ngay cả trong lúc duyệt nó. Các thao tác trên ConcurrentHashMap đều có tính an toàn luồng. ConcurrentHashMap không cho phép key và value có giá trị là null.

Ví dụ về ConcurrentHashMap trong Java

Class ConcurrentHashMap tương tự như HashMap, chỉ khác ở chỗ nó có tính an toàn luồng và cho phép chỉnh sửa collection ngay trong khi duyệt.

package com.journaldev.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {

	public static void main(String[] args) {

		//ConcurrentHashMap
		Map myMap = new ConcurrentHashMap();
		myMap.put("1", "1");
		myMap.put("2", "1");
		myMap.put("3", "1");
		myMap.put("4", "1");
		myMap.put("5", "1");
		myMap.put("6", "1");
		System.out.println("ConcurrentHashMap before iterator: "+myMap);
		Iterator it = myMap.keySet().iterator();

		while(it.hasNext()){
			String key = it.next();
			if(key.equals("3")) myMap.put(key+"new", "new3");
		}
		System.out.println("ConcurrentHashMap after iterator: "+myMap);

		//HashMap
		myMap = new HashMap();
		myMap.put("1", "1");
		myMap.put("2", "1");
		myMap.put("3", "1");
		myMap.put("4", "1");
		myMap.put("5", "1");
		myMap.put("6", "1");
		System.out.println("HashMap before iterator: "+myMap);
		Iterator it1 = myMap.keySet().iterator();

		while(it1.hasNext()){
			String key = it1.next();
			if(key.equals("3")) myMap.put(key+"new", "new3");
		}
		System.out.println("HashMap after iterator: "+myMap);
	}

}

Output:

ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
	at java.util.HashMap$KeyIterator.next(HashMap.java:828)
	at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)

Ta có thể thấy rõ rằng ConcurrentHashMap xử lý được việc thêm phần tử mới vào map ngay trong khi duyệt, trong khi HashMap lại gây ra lỗi . Cùng xem kỹ stack trace (thông tin các hàm gọi bị lỗi). Lỗi này được gây ra bởi câu lệnh sau.

String key = it1.next();

Điều này có nghĩa là phần tử mới đã được thêm vào HashMap, nhưng iterator (bộ lặp) lại gặp lỗi. Thực tế, iterator trên các đối tượng Collection có cơ chế fail-fast, tức là bất kỳ thay đổi nào về cấu trúc hay số lượng phần tử của collection đều sẽ gây ra lỗi ngay lập tức.

Làm sao iterator biết collection đã bị chỉnh sửa?

Ta đã lấy ra một set các key từ HashMap rồi duyệt qua set đó. HashMap có chứa một biến dùng để đếm số lần collection bị chỉnh sửa. Iterator sẽ sử dụng biến này mỗi khi ta gọi phương thức next() của nó để lấy entry tiếp theo.

/**
     * The number of times this HashMap has been structurally modified
     * Structural modifications are those that change the number of mappings in
     * the HashMap or otherwise modify its internal structure (e.g.,
     * rehash).  This field is used to make iterators on Collection-views of
     * the HashMap fail-fast.  (See ConcurrentModificationException).
     */
    transient volatile int modCount;

Giờ hãy thay đổi code một chút để thoát khỏi vòng lặp của iterator ngay khi ta thêm một phần tử mới. Ta chỉ cần thêm một câu lệnh break ngay sau lệnh put.

if(key.equals("3")){
	myMap.put(key+"new", "new3");
	break;
}

Output với đoạn code trên như dưới:

ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1}

Điều gì xảy ra nếu giá trị của key bị chỉnh sửa?

Sẽ ra sao nếu ta không thêm một phần tử mới mà chỉ cập nhật một cặp key-value đã tồn tại? Liệu chương trình có gây ra lỗi không**?** Hãy cùng thay đổi code trong chương trình gốc và xem thử kết quả.

//myMap.put(key+"new", "new3");
myMap.put(key, "new3");

Sẽ không có lỗi nào xảy ra, bởi vì dù collection đã bị chỉnh sửa, cấu trúc của nó vẫn được giữ nguyên.

Đọc thêm

Bạn có để ý các dấu ngoặc nhọn khi ta tạo đối tượng collection và iterator không? Chúng được gọi là generics, một tính năng rất mạnh mẽ trong việc kiểm tra kiểu (type-checking) tại lúc compile để loại bỏ lỗi ClassCastException tại lúc runtime.

Hãy tìm đọc các bài viết khác của chúng tôi để hiểu thêm về generics cũng như các câu hỏi phỏng vấn về Java Collection cũng như kiểu thiết kế Iterator trong Java.

Về tác giả

Chris Pham
Chris PhamTechnical Writer

I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.

Cập nhật thông tin mới nhấtNhận các thông tin mới nhất về mối đe dọa, báo cáo an ninh mạng từ CyStack về hòm thư điện tử của bạn

Thảo luận (0)

Đăng nhập để thảo luận

Bài viết liên quan