2009-09-16 37 views
31

Tôi không chắc chắn đây có phải là cách chính xác để đồng bộ hóa ArrayList của tôi không.Cách đúng để đồng bộ hóa ArrayList trong java

Tôi có một số ArrayListin_queue được chuyển từ hàm registerInQueue.

ArrayList<Record> in_queue = null; 

public void registerInQueue(ArrayList in_queue) 
{ 
    this.in_queue = in_queue; 
} 

Bây giờ tôi đang cố gắng đồng bộ hóa. Điều này có đồng bộ hóa đối tượng in_queue của tôi một cách chính xác không?

List<Record> in_queue_list = Collections.synchronizedList(in_queue); 

synchronized (in_queue_list) { 
    while (in_queue_list.size() > 0) { 
     in_queue_list.remove(0); 
    } 
} 
+5

Bạn thực sự không thể nâng cấp danh sách được đồng bộ hóa vì bạn đang chuyển một tham chiếu, vì vậy bạn không thực sự sở hữu nó. Bất cứ điều gì đã cho bạn các tài liệu tham khảo vẫn có thể sửa đổi danh sách ban đầu nó thông qua bạn đồng thời. Bất kể bạn đồng bộ hóa gì, trừ khi nó được biết rõ ràng rằng danh sách sẽ được bảo vệ bởi khóa nội tại của nó. –

+0

Tôi sẽ đặt một khối đồng bộ xung quanh bất kỳ thao tác nào trên hàng đợi. Cảm ơn! – bob

Trả lời

41

Bạn đang đồng bộ hóa hai lần, đó là vô nghĩa và có thể làm chậm xuống mã: Những thay đổi trong khi iterating trên danh sách cần một synchronnization so với toàn bộ hoạt động , mà bạn đang làm với synchronized (in_queue_list) Sử dụng Collections.synchronizedList() là thừa trong trường hợp đó (nó tạo ra một trình bao bọc đồng bộ hóa các hoạt động riêng lẻ).

Tuy nhiên, vì bạn đang dọn sạch danh sách hoàn toàn, việc xóa bỏ phần tử đầu tiên là cách tồi tệ nhất có thể để làm điều đó, cho mỗi phần tử tất cả các phần tử sau phải được sao chép, làm cho nó trở thành O (n^2) hoạt động - khủng khiếp chậm cho các danh sách lớn hơn.

Thay vào đó, chỉ cần gọi clear() - không cần lặp lại.

Edit: Nếu bạn cần đồng bộ hóa đơn phương pháp Collections.synchronizedList() sau này, thì đây là cách chính xác:

List<Record> in_queue_list = Collections.synchronizedList(in_queue); 
in_queue_list.clear(); // synchronized implicitly, 

Nhưng trong nhiều trường hợp, đồng bộ hóa đơn phương là không đủ (ví dụ cho tất cả các lần lặp lại hoặc khi bạn nhận được một giá trị, hãy tính toán dựa trên nó và thay thế nó bằng kết quả). Trong trường hợp đó, bạn phải sử dụng đồng bộ hóa thủ công, vì vậy, Collections.synchronizedList() chỉ là phí bổ sung vô ích.

+7

Đồng bộ hóa hai lần ở đây không phải là vô nghĩa: nó đảm bảo rằng trong khi vòng lặp đang chạy không ai khác có thể sửa đổi danh sách. Tuy nhiên, không sử dụng 'clear()' là một bit over-the-top. :) – Bombe

+0

vì vậy tôi nên làm một cái gì đó như: đồng bộ ((List) in_queue)? – bob

+0

Ok! Tôi thực sự đã xóa một chút mã để làm cho nó đơn giản. Tôi sẽ không gặp vấn đề gì với clear()/remove(). thanks =] – bob

5

Có đúng cách, nhưng khối được đồng bộ là bắt buộc nếu bạn muốn tất cả các lần xóa cùng nhau được an toàn - trừ khi hàng đợi trống không được phép xóa. Tôi đoán là bạn chỉ muốn hàng đợi an toàn và hoạt động dequeue, vì vậy bạn có thể loại bỏ khối đồng bộ.

Tuy nhiên, có hàng đợi đồng thời xa tiên tiến trong Java như ConcurrentLinkedQueue

8

Nhìn vào ví dụ của bạn, tôi nghĩ rằng ArrayBlockingQueue (hoặc anh chị em của nó) có thể được sử dụng. Họ xem xét việc đồng bộ hóa cho bạn, do đó, các luồng có thể ghi vào hàng đợi hoặc xem/không thực hiện đồng bộ hóa thêm về phía bạn.

+0

Cảm ơn bạn đã đề xuất! Đó là những gì tôi đang cố gắng làm, không chắc chắn về hạn chế kích thước của mảng của tôi mặc dù. Tôi sẽ ghi nhớ điều này. ;) – bob

+0

Lưu ý có một LinkedBlockingQueue là tốt. Và bạn không nhất thiết phải áp đặt giới hạn. –

+0

cảm ơn, tôi sẽ nhớ điều này =] – bob

1

Hãy lấy một danh sách bình thường (được thực hiện bởi lớp ArrayList) và làm cho nó được đồng bộ hóa. Điều này được thể hiện trong lớp SynchronizedListExample. Chúng ta chuyển phương thức Collections.synchronizedList một ArrayList mới của Strings. Phương thức này trả về một List of Strings đã đồng bộ. // Đây là lớp SynchronizedArrayList

package com.mnas.technology.automation.utility; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Iterator; 
import java.util.List; 
import org.apache.log4j.Logger; 
/** 
* 
* @author manoj.kumar 
* @email [email protected] 
* 
*/ 
public class SynchronizedArrayList { 
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName()); 
    public static void main(String[] args) {  
     List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>()); 
     synchronizedList.add("Aditya"); 
     synchronizedList.add("Siddharth"); 
     synchronizedList.add("Manoj"); 
     // when iterating over a synchronized list, we need to synchronize access to the synchronized list 
     synchronized (synchronizedList) { 
      Iterator<String> iterator = synchronizedList.iterator(); 
      while (iterator.hasNext()) { 
       log.info("Synchronized Array List Items: " + iterator.next()); 
      } 
     }  
    } 
} 

Chú ý rằng khi iterating trên danh sách, truy cập này vẫn thực hiện bằng một khối đồng bộ mà khóa trên đối tượng synchronizedList. Nói chung, việc lặp qua bộ sưu tập được đồng bộ hóa phải được thực hiện trong khối đồng bộ

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