2010-05-19 24 views
7

vì vậy tôi muốn có một danh sách chuỗi lưu trữ một loạt các trích dẫn chứng khoán. nhưng tôi theo dõi giá dự thầu, hỏi giá và giá cuối cùng cho mỗi giá.đồng bộ hóa số lần đọc vào bộ sưu tập java

tất nhiên bất kỳ lúc nào, yêu cầu giá thầu hoặc cuối cùng của một cổ phiếu nhất định có thể thay đổi.

tôi có một chuỗi cập nhật giá và một chủ đề đọc chúng.

tôi muốn đảm bảo rằng khi đọc không có chủ đề nào khác đang cập nhật giá. vì vậy tôi đã xem bộ sưu tập được đồng bộ hóa. nhưng điều đó dường như chỉ ngăn chặn việc đọc trong khi một luồng khác đang thêm hoặc xóa một mục nhập vào danh sách mảng.

vì vậy bây giờ tôi vào cách tiếp cận wrapper:

public class Qte_List { 
private final ArrayList<Qte> the_list; 

public void UpdateBid(String p_sym, double p_bid){ 
    synchronized (the_list){ 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     q.bid=p_bid;} 
} 

public double ReadBid(String p_sym){ 
    synchronized (the_list){ 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     return q.bid;} 
} 

vì vậy những gì tôi muốn đạt được với điều này là chỉ có một thread có thể được thực hiện bất cứ điều gì - đọc hoặc cập nhật nội dung của một the_list - cùng một lúc. tôi đang tiếp cận quyền này?

cảm ơn.

+0

Bạn đang cố gắng ngăn việc ghi vào đối tượng Trích dẫn xảy ra cùng lúc với một lần đọc không? Nếu vậy, khóa bộ sưu tập sẽ không thực hiện được điều này. Xem câu trả lời của tôi. – DJClayworth

Trả lời

0

Vì tôi hiểu rằng bạn đang sử dụng bản đồ để lưu trữ các dấu ngoặc kép; số lượng dấu ngoặc kép không bao giờ thay đổi, nhưng mỗi trích dẫn có thể được đọc hoặc sửa đổi để phản ánh giá hiện tại. Điều quan trọng cần biết là việc khóa bộ sưu tập chỉ bảo vệ chống lại những thay đổi mà đối tượng Trích dẫn có trong bản đồ: nó không có bất kỳ cách nào hạn chế việc sửa đổi nội dung của các Báo giá đó. Nếu bạn muốn hạn chế quyền truy cập đó, bạn sẽ phải cung cấp khóa trên đối tượng Trích dẫn.

Nhìn vào mã của bạn tuy nhiên tôi không tin rằng bạn gặp sự cố đồng bộ hóa đáng kể. Nếu bạn cố gắng đọc cùng một lúc như viết, bạn sẽ nhận được giá trước hoặc giá sau khi viết. Nếu bạn không biết viết sẽ xảy ra mà không quan trọng với bạn. Bạn có thể cần khóa ở mức cao hơn để

if (getBidPrice(mystock)<10.0) { 
    sell(10000); 
} 

xảy ra dưới dạng hoạt động nguyên tử và bạn không kết thúc bán ở mức 5.0 thay vì 10.0.

Nếu số lượng dấu ngoặc kép thực sự không thay đổi thì tôi khuyên bạn nên chỉ cho phép các đối tượng Qte được thêm vào chỉ trong hàm tạo của Qte_List. Điều này sẽ làm cho khóa bộ sưu tập không liên quan. Thuật ngữ kỹ thuật cho việc này là làm cho Qte_List không thay đổi.

+0

cảm ơn bạn khiến tôi nghĩ rằng tôi cần làm rõ chính xác hơn những gì cần khóa. sẽ ăn nó một vài giờ. – jeff

+0

DJ - ngoài ra, tôi nghĩ rằng tôi đã nhận được bản thân mình bối rối bây giờ trong cố gắng suy nghĩ thông qua điều này. Tôi đang nhìn vào những gì bạn đã viết đậm hơn ở trên .... sự khác biệt giữa khóa trên một bộ sưu tập và đánh dấu nó là gì? tôi nghĩ rằng đánh dấu nó cuối cùng là những gì ngăn chặn những thay đổi mà các đối tượng có trong bản đồ. – jeff

+0

@Jeff cuối cùng chỉ tuyên bố biến là "bất biến", không phải là đối tượng tại biến. Vì vậy, Danh sách vẫn có thể thay đổi. Nếu bạn muốn Danh sách không thay đổi, hãy xem 'Collections.unmodifiableList() ' – Hardcoded

1

Có điều này sẽ làm việc, dù sao bạn không cần phải làm điều đó cho mình vì nó đã được thực hiện trong khuôn khổ Bộ sưu tập

Collections.synchronizedList

+1

Danh sách được đồng bộ hóa sẽ không hoạt động, vì anh ta cập nhật các thuộc tính của các mục nhập trong danh sách trong khối được đồng bộ hóa – Hardcoded

1

Trông giống như một cách tiếp cận hợp lý. Nit-hái, tuy nhiên, có lẽ bạn nên không bao gồm các câu lệnh return bên trong khối đồng bộ:

public double ReadBid(String p_sym){ 
    double bid; 
    synchronized (the_list) { 
     Qte q = Qte.FindBySym(the_list, p_sym); 
     bid = q.bid; 
    } 

    return bid; 
} 

Tôi không chắc chắn nếu nó chỉ là hương vị của tôi hoặc có một số Gotcha đồng thời tham gia, nhưng ít nhất nó trông sạch hơn với tôi ;-).

2

Có, bạn đang đi đúng hướng và điều đó sẽ hoạt động.

Nhưng tại sao không sử dụng bộ sưu tập Hashtable hiện tại, được đồng bộ hóa và cung cấp tra cứu khóa-giá trị?

+2

Hashtable (và Vector) là tiền JDK 1.2 và nên tránh. Thay vào đó, hãy xem xét Collections.synchronizedMap (Map m) để tạo HashMap an toàn cho luồng. Ngoài ra, mặc dù OP đã không tuyên bố rõ ràng, tôi nghi ngờ rằng các dấu ngoặc kép cần phải được đặt hàng theo một thứ tự điển hình. – Adamski

1

Cách tiếp cận của bạn nên thực hiện thủ thuật, nhưng như bạn đã nói, chỉ có thể có một người đọc và người viết tại một thời điểm. Điều này không phải là rất khả năng mở rộng.

Có một số cách để cải thiện hiệu suất mà không mất chủ đề an toàn ở đây.
Bạn có thể sử dụng ví dụ ReadWriteLock. Điều này sẽ cho phép nhiều người đọc cùng một lúc, nhưng khi ai đó nhận được khóa ghi, tất cả những người khác phải đợi anh ta kết thúc.

Một cách khác là sử dụng bộ sưu tập phù hợp. Có vẻ như bạn có thể trao đổi danh sách của mình với việc triển khai an toàn theo chủ đề Map. Hãy xem ConcurrentMap documentation cho các ứng cử viên có thể.

Edit:
Giả sử rằng bạn không cần ra lệnh cho đồ của bạn, có một cái nhìn tại giao diện ConcurrentNavigableMap.

1

Những gì bạn có sẽ hoạt động, nhưng khóa toàn bộ danh sách mỗi lần bạn muốn đọc hoặc cập nhật giá trị của phần tử không thể mở rộng. Nếu điều này không quan trọng, thì bạn ổn với những gì bạn có. Nếu bạn muốn làm cho nó có thể mở rộng hơn, hãy xem xét những điều sau đây ...

Bạn không nói liệu bạn có cần thực hiện thay đổi cấu trúc cho the_list (thêm hoặc xóa các phần tử) hay không, nhưng nếu không, thì một cải tiến lớn sẽ là chuyển cuộc gọi đến FindBySym() bên ngoài khối được đồng bộ hóa. Sau đó, thay vì đồng bộ hóa trên the_list, bạn chỉ có thể đồng bộ hóa trên q (đối tượng Qte). Bằng cách đó bạn có thể cập nhật các đối tượng Qte khác nhau đồng thời. Ngoài ra, nếu bạn có thể làm cho các đối tượng Qte không thay đổi thì bạn thực sự không cần bất kỳ sự đồng bộ nào cả. (để cập nhật, chỉ cần sử dụng the_list [i] = new Qte (...)).

Nếu bạn cần để có thể thực hiện thay đổi cấu trúc cho danh sách, bạn có thể sử dụng một ReentrantReadWriteLock để cho phép đọc đồng thời và ghi độc quyền.

Tôi cũng tò mò tại sao bạn muốn sử dụng ArrayList thay vì HashMap được đồng bộ hóa.

+0

có vẻ như một hashmap có ý nghĩa hơn nhiều. tôi có thể mặc định để liệt kê quá nhiều mà không cần suy nghĩ. điều bất biến trên một đối tượng Qte có thể giúp giải quyết vấn đề. nhưng tôi cần phải làm việc nhiều hơn một chút để hiểu nó. cú pháp làm cho đối tượng Qte bất biến là gì, hoặc tôi sẽ tìm kiếm. cũng có, không thay đổi có nghĩa là 'thay đổi' đối tượng tôi cần phải gán lại nó? (Tôi đang xem văn bản trong câu trả lời cho biết, "để cập nhật, chỉ cần sử dụng the_list [i] = new Qte (...)" – jeff

+0

Không thể thay đổi có nghĩa là "không thể thay đổi" .Ví dụ Strings không thay đổi, trong khi StringBuffers là Bạn không thể thay đổi giá trị của đối tượng String (ví dụ: bạn không thể nói String s = "a"; s.append ("b"); Lớp Qte không thay đổi sẽ có giá thầu, hãy hỏi giá và giá cuối cùng là các biến thành viên cuối cùng và 3 giá trị này sẽ được chuyển vào hàm khởi tạo, các biến thành viên có thể được công khai hoặc bạn có thể có một getter (nhưng không có setter) cho mỗi số – Angus

+0

Ngoài ra, về nhận xét của DJClayworth lấy giá trước hoặc giá sau khi viết ", điều này chỉ đúng nếu Qte.bid là giá trị 32 bit (hoặc ít hơn) hoặc dễ bay hơi.Đối với các giá trị không bay hơi 64 bit, có thể đọc ở giữa ghi và nhận dữ liệu xấu (xem thông số ngôn ngữ java, phần 17.7 để biết chi tiết), do đó bạn cần thay đổi Qte.bid thành float hoặc int hoặc để cho nó một đôi và tuyên bố nó dễ bay hơi (nếu nó chưa được). Khi đã xong, bạn có thể đọc và ghi một cách an toàn q.bid mà không cần đồng bộ hóa. (và bạn có thể bỏ qua gợi ý bất biến của tôi) – Angus

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