2012-01-16 16 views
35

Theo như tôi biết, java.util.Hashtable đồng bộ hóa mỗi phương pháp trong giao diện java.util.Map, trong khi Collections.synchronizedMap(hash_map) trả về một đối tượng wrapper chứa phương pháp đồng bộ ủy thác cuộc gọi đến thực tế hash_map (chính xác cho tôi nếu tôi là sai).Sự khác nhau giữa Hashtable và Collections.synchronizedMap (HashMap)

Tôi có hai câu hỏi:

  1. hiện nó làm cho sự khác biệt gì để đồng bộ hóa mỗi và mọi phương pháp và có một lớp bao bọc? Các kịch bản để chọn một kịch bản khác là gì?

  2. Điều gì sẽ xảy ra khi chúng tôi thực hiện Collections.synchronizedMap(hash_table)? Điều này có bằng đơn giản bằng cách sử dụng thông thường java.util.Hashtable không?

+0

có thể trùng lặp của [Sự khác biệt giữa HashMap và Hashtable?] (Http://stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable) –

+13

Đây không phải là bản sao của câu hỏi * đó *. Đây là so sánh trình bao bọc được đồng bộ hóa trên HashMap (hoặc HashTable) với một HashTable. –

+0

Tôi muốn được quan tâm để biết nếu có sự khác biệt về hiệu suất, mà không có địa chỉ trả lời hiện tại. Các phương thức gọi của 'Collections.synchronizedMap' thông qua biến kiểu Map có nghĩa là có 2 cuộc gọi ảo giao diện trước khi bạn thực hiện, trong khi với Hashtable, có tối đa 1 cuộc gọi ảo và bạn có thể khai báo biến của bạn dưới dạng Hashtable trực tiếp và thực hiện với 0 cuộc gọi ảo. Nhưng có lẽ HashMap khác nhau theo những cách khác làm cho nó nhanh hơn tổng thể. – Boann

Trả lời

13

Dưới đây là câu trả lời tôi đã nhận được từ một chút (hy vọng đúng) nghiên cứu:

  1. Cả hai cung cấp cùng một mức độ đồng bộ hóa. Nếu bạn đã bọc Hashtable thông qua Collections.synchronized, bạn sẽ có cùng một mức độ, nhưng với một lớp dự phòng khác, của đồng bộ hóa.

  2. Sự khác biệt chính giữa HashtableCollections.synchronizedMap(HashMap) tồn tại nhiều hơn ở cấp API. Bởi vì Hashtable là một phần của mã kế thừa của Java, bạn sẽ thấy rằng API Hashtable được tăng cường để triển khai giao diện Map, để trở thành một phần của khung bộ sưu tập của Java. Điều này có nghĩa là nếu bạn đã quấn Hashtable qua Collections.synchronizedMap(), API của gói Hashtable sẽ bị giới hạn ở API Map. Vì vậy, nếu API của Hashtable được bao gồm trong định nghĩa của bạn về hành vi , thì rõ ràng là bị thay đổi/giới hạn.

1

Lúc nguy cơ nêu rõ ràng (hoặc là đồng bằng sai) không phải là sự khác biệt mà

Các wrappers đồng bộ hóa tự động đồng bộ hóa thêm (thread-an toàn) đến một bộ sưu tập độc đoán

http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html và tiếp tục nói

Một bộ sưu tập được tạo trong thời trang này có kích thước chỉ là một bộ sưu tập thông thường được đồng bộ hóa, chẳng hạn như Vector.

Bạn có thể muốn xem chuỗi này về các vấn đề liên quan đến HashMaps và đồng thời - Hashmap concurrency issue (hoặc có thể bạn đã biết rất nhiều về chúng). Một ví dụ tốt là:

Các điều kiện bạn mô tả sẽ không được HashMap thỏa mãn. Vì quá trình cập nhật bản đồ không phải là nguyên tử, bạn có thể gặp phải bản đồ ở trạng thái không hợp lệ. Nhiều lần viết có thể để nó ở trạng thái bị lỗi . ConcurrentHashMap (1.5 hoặc mới hơn) thực hiện những gì bạn muốn.

https://stackoverflow.com/a/1003071/201648

Tôi đoán về "khi tôi nên sử dụng này:" Tôi sẽ có xu hướng sử dụng bộ sưu tập syncronised nơi đồng thời là cần thiết, nếu không bạn có thể tạo ra nhiều việc hơn cho chính mình (xem dưới đây).

Xét về thay đổi hành vi

Nếu một iterator rõ ràng được sử dụng, phương pháp lặp phải được gọi từ bên trong khối đồng bộ. Thất bại trong việc làm theo lời khuyên này có thể dẫn đến hành vi không xác định

Có nhiều hậu quả của việc sử dụng đồng bộ hóa được đưa ra vào (Oracle) liên kết được cung cấp.

4

Lớp thu thập liên kết đầu tiên xuất hiện trong thư viện lớp Java là là Hashtable, là một phần của JDK 1.0. Hashtable cung cấp khả năng bản đồ liên kết, an toàn, dễ sử dụng, và nó là chắc chắn thuận tiện. Tuy nhiên, thread-safety có giá - tất cả các phương thức của Hashtable được đồng bộ hóa. Vào thời điểm đó, đồng bộ hóa không được kiểm soát có chi phí hiệu suất có thể đo lường. Người kế thừa Hashtable, HashMap, xuất hiện như một phần của khung Collections trong JDK 1.2, giải quyết an toàn luồng bằng cách cung cấp một lớp cơ sở không đồng bộ và một trình bao bọc đồng bộ, Collections.synchronizedMap. Tách chức năng cơ sở từ Bản đồ Thread-safety Collections.synchronizedMap cho phép người dùng cần đồng bộ hóa để có nó, nhưng người dùng không cần nó không có để thanh toán.

Cách tiếp cận đơn giản để đồng bộ hóa được Hashtable và đồng bộ hóa Bản đồ - đồng bộ hóa từng phương pháp trên đối tượng bao bọc Bản đồ được đồng bộ hóa với Hashtable hoặc - có hai thiếu sót chính. Nó là một trở ngại đối với khả năng mở rộng, bởi vì chỉ có một luồng có thể truy cập bảng băm tại một thời điểm. Đồng thời, nó không đủ để cung cấp sự an toàn chủ đề thực sự, trong đó nhiều hoạt động hợp chất phổ biến vẫn yêu cầu đồng bộ hóa bổ sung. Trong khi thao tác đơn giản như vậy như get() và put() có thể hoàn thành một cách an toàn mà không cần thêm đồng bộ , có một số hoạt động phổ biến, chẳng hạn như lặp lại hoặc bỏ-nếu-vắng mặt, mà vẫn yêu cầu đồng bộ bên ngoài để tránh các cuộc đua dữ liệu .

Các liên kết sau đây là nguồn gốc và có thêm thông tin: Concurrent Collections Classes

+1

Đoạn thứ hai nói rằng 'Hashtable' và' synchronMap' là giống nhau. Điều đó có nghĩa là chúng tôi chưa trả lời được câu hỏi: Sự khác biệt của họ là gì? – Pacerier

+0

đọc câu trả lời của @mankadnandan –

3

Sự khác biệt không phải là tất cả ở cấp API rõ ràng và có rất nhiều sự tinh tế ở mức độ thực hiện. Ví dụ: Hashtable không thể tính toán lại các mã băm của khóa được cung cấp nâng cao để giảm va chạm băm của HashMap. Mặt khác, Hashtable#hashCode() tránh việc đệ quy vô hạn cho các hashtables tự tham chiếu để cho phép "các ứng dụng nhất định 1,1 tuổi có bảng băm tự tham chiếu hoạt động".

Nói chung, tuy nhiên, người ta không nên dựa vào Hashtable nhận được bất kỳ cải tiến hoặc cải tiến nào khác ngoài tính chính xác cơ bản và tính tương thích ngược. Nó được coi là một di tích từ quá khứ Java sâu.

45

Một sự khác biệt nữa mà tôi có thể tìm thấy ở việc thực hiện của cả lớp là như sau:

• Lớp Hashtable có tất cả các phương pháp của nó đồng bộ tức là khóa được làm ở cấp phương pháp và do đó người ta có thể nói rằng mutex là luôn là ở mức Hashtable đối tượng (this).

• Phương pháp Collections.synchronizedMap(Map) trả về phiên bản SynchronizedMap là lớp bên trong cho lớp Collections. Lớp này có tất cả các phương thức của nó trong một khối Synchronized với một mutex. Sự khác biệt nằm ở mutex ở đây. Lớp bên trong là SynchronizedMap có hai hàm tạo, chỉ có một đối số là Map và một đối số khác lấy một số Map và một đối số là một đối số. Theo mặc định, nếu người dùng sử dụng hàm tạo đầu tiên chỉ truyền một số Map, this được sử dụng làm mutex. Mặc dù, nhà phát triển được phép chuyển đối tượng mutex khác làm đối số thứ hai mà khóa trên phương thức Map sẽ chỉ ở trên Object và do đó ít hạn chế hơn Hashtable.

• Do đó, Hashtable sử dụng đồng bộ hóa mức phương thức nhưng Collections.synchronizedMap(Map) cung cấp tính linh hoạt cho khóa nhà phát triển trên mutex được cung cấp với khối Synchronized.

+2

Thật là một câu trả lời hay, nhấn mạnh những gì không bị ảnh hưởng nếu không có câu trả lời còn lại. +1 –

+3

Thêm hàm tạo và đồng bộ hóa ở cấp khối (không giống như mức phương thức cho HashTable) là các khóa. –

+3

Đây thực sự là thông tin thú vị, nhưng lớp SynchronizedMap bên trong là riêng tư, và không có phương thức tĩnh tương ứng với phiên bản của hàm tạo chấp nhận đối tượng mutex làm đối số, vì vậy nhà phát triển không thể cung cấp một mutex tùy chỉnh, đúng không? – CarLuva