2012-11-08 29 views
5

Tôi đã có một trường hợp sử dụng cụ thể nhưng không thể tìm ra cấu trúc dữ liệu phù hợp để sử dụng.Cấu trúc dữ liệu Java lý tưởng cho dữ liệu trực tuyến

Tôi có một chuỗi giữ các đối tượng phát trực tiếp vào HashMap. Một cái gì đó tương tự như dữ liệu thị trường, nơi bạn có một tần số cao và không rõ của ve.

Một chủ đề khác liên tục đọc bản đồ này để cập nhật Đối tượng giá và truy vấn theo khóa không theo thứ tự cụ thể. Các truy vấn có thể nhiều lần cho cùng một khóa trong một chu kỳ nhất định. Việc đọc và ghi là rất thường xuyên nhưng các chủ đề đọc chỉ quan tâm đến các dữ liệu mới nhất có sẵn được cập nhật đầy đủ và không nhất thiết phải chặn cho đến khi viết xong.

Tôi muốn suy nghĩ của bạn về cấu trúc dữ liệu lý tưởng cho các trường hợp sử dụng đó. Có triển khai tốt hơn ConcurrentHashMap có sẵn không?

Cảm ơn

+0

sẽ sửa đổi hashmap (tức là sẽ có đặt và xóa) trong khi dữ liệu đánh dấu được cập nhật? hoặc các ánh xạ sẽ được thiết lập trước khi dữ liệu bắt đầu đến? – mxns

+0

có sẽ có rất nhiều đặt nhưng không có loại bỏ. Về cơ bản trên mỗi tick đến, tôi sẽ làm một put (key, Price). Mặt khác, tôi cũng có thể prepopulate hashMap với một số đối tượng giả, vì tôi biết các phím trước khi tay. – trequartista

+0

Chìa khóa là gì? Chứng khoán? –

Trả lời

1

Một cách tiếp cận sẽ là một chương trình copy-on-write, một cái gì đó như thế này:

public class Prices { 
    private volatile Map<String, Integer> prices = Collections.emptyMap(); 

    public void putPrice(String ticker, int price) { 
     HashMap<String, Integer> newPrices = new HashMap<String, Integer>(prices); 
     newPrices.put(ticker, price); 
     prices = newPrices; 
    } 

    public Integer getPrice(String ticker) { 
     return prices.get(ticker); 
    } 
} 

này có chi phí tối thiểu cho được - một đọc từ một ổn định, và sau đó một tra cứu băm bình thường. Tuy nhiên, nó có một chi phí đáng kể cho đặt - việc tạo ra một bản đồ hoàn toàn mới, cộng với một ghi vào một biến động. Nếu tỷ lệ đọc của bạn để viết cao, điều này vẫn có thể là một sự cân bằng tốt.

Bạn có thể cải thiện điều này bằng cách chỉ tắt bản đồ khi bạn thực sự cần thêm mục nhập mới, thay vì cập nhật mục nhập hiện có; bạn có thể đạt được điều đó bằng cách sử dụng các giá trị có thể thay đổi:

public class Prices { 
    private volatile Map<String, AtomicInteger> prices = Collections.emptyMap(); 

    public void putPrice(String ticker, int price) { 
     AtomicInteger priceHolder = prices.get(ticker); 
     if (priceHolder != null) { 
      priceHolder.set(price); 
     } 
     else { 
      HashMap<String, AtomicInteger> newPrices = new HashMap<String, AtomicInteger>(prices); 
      newPrices.put(ticker, new AtomicInteger(price)); 
      prices = newPrices; 
     } 
    } 

    public Integer getPrice(String ticker) { 
     AtomicInteger priceHolder = prices.get(ticker); 
     if (priceHolder != null) return priceHolder.get(); 
     else return null; 
    } 
} 

Tôi không chắc chắn những gì các đặc tính hiệu suất của một AtomicInteger là; nó có thể là chậm hơn so với nó có vẻ. Giả sử AtomicInteger không phải là bất hợp lý chậm, điều này sẽ khá nhanh - nó liên quan đến hai lần đọc từ một biến động cộng với một tra cứu băm bình thường cho mỗi get, và đọc từ một biến động, tra cứu băm và một ghi đơn để dễ bay hơi để cập nhật giá hiện tại. Nó vẫn liên quan đến việc sao chép bản đồ để bổ sung giá mới. Tuy nhiên, trong một thị trường điển hình, điều đó không xảy ra thường xuyên.

2

ConcurrentHashMap. Từ Javadoc

Bảng băm hỗ trợ đồng thời đầy đủ các lần truy xuất và điều chỉnh đồng thời dự kiến ​​để cập nhật. Lớp này tuân theo cùng một đặc tả chức năng như Hashtable và bao gồm các phiên bản của phương thức tương ứng với mỗi phương pháp của Hashtable. Tuy nhiên, mặc dù tất cả các hoạt động hoạt động an toàn chỉ, yêu cầu truy xuất không yêu cầu khóa và không có bất kỳ hỗ trợ nào để khóa toàn bộ bảng trong một cách ngăn chặn tất cả quyền truy cập. Lớp này hoàn toàn tương thích với Hashtable trong các chương trình dựa trên sự an toàn của luồng nhưng không phải trên chi tiết đồng bộ của nó.

Hoạt động truy xuất (bao gồm nhận) thường không chặn, vì vậy có thể trùng lặp với các thao tác cập nhật (bao gồm đặt và xóa). Retrievals phản ánh kết quả của các hoạt động cập nhật mới nhất được hoàn thành giữ khi khởi động. Đối với các phép toán tổng hợp như putAll và , các lần truy xuất đồng thời có thể phản ánh việc chèn hoặc xóa chỉ một số mục nhập. Tương tự, các Iterator và Enumerations trả về các phần tử phản ánh trạng thái của bảng băm tại một số điểm tại hoặc từ khi tạo ra một vòng lặp/liệt kê .

1

Nếu bản đồ không bị sửa đổi (nghĩa là không đặt hoặc xóa) trong khi dữ liệu đang được cập nhật, bạn thậm chí không cần bản đồ đồng bộ như ConcurrentHashMap. Nếu có đặt và xóa liên tục trong quá trình thực hiện chương trình, bạn cần phải đồng bộ hóa các cuộc gọi này. Tuy nhiên, ngay cả một ConcurrentHashMap bắt đầu ném ConcurrentModificationExceptions tất cả xung quanh khi tần số cập nhật lên đến cao (trong một chương trình đa luồng). Tần suất nào quá cao? Bạn có thể phải đo lường chính mình, nó phụ thuộc vào rất nhiều yếu tố trong nền tảng của bạn.

Điều tôi làm trong những trường hợp này, tôi cố gắng tạo ra một tình huống mà tôi không phải chèn hoặc xóa khỏi bản đồ trong khi thực hiện chương trình, chỉ khi khởi động và tắt khi luồng dữ liệu bị dừng. Nếu điều đó là không thể, tôi sử dụng kết hợp HashMap bình thường và cấu trúc dữ liệu tuyệt vời CopyOnWriteArrayList và đồng bộ hóa bên ngoài. Tôi đã không kiểm tra các giới hạn của ConcurrentHashMap, nhưng tôi sẽ không tin tưởng nó cho các hệ thống sản xuất của riêng tôi.

EDIT: ConcurrentHashMap KHÔNG gây ra bất kỳ ConcurrentModificationExceptions nào, chỉ khi bạn sử dụng Bộ sưu tập.syncMap bạn có thể gặp rắc rối.

+0

Bạn có thể giải thích loại ngoại lệ nào được ném xung quanh và trong trường hợp ConcurrentHashMap có tần suất cập nhật cao hay không –

+0

@Pangea đã chỉnh sửa để trả lời câu hỏi của bạn nhiều hơn một chút – mxns

+0

Tôi cũng đã sử dụng CopyOnWriteArrayList. câu hỏi của tôi là về tuyên bố của bạn "Tuy nhiên, ngay cả một ConcurrentHashMap bắt đầu ném ConcurrentModificationExceptions tất cả xung quanh khi tần số cập nhật được cao" –

Các vấn đề liên quan