2012-12-19 25 views
5


Tôi đã viết mã bên dưới trong phương thức nhà máy tĩnh để trả về cá thể đơn của DefaultCache.Phương pháp của nhà máy để tạo ra cá thể đơn lẻ

public static ICache getInstance() { 
    if (cacheInstance == null) { 
     synchronized (ICache.class) { 
     if (cacheInstance == null) { 
      cacheInstance = new DefaultCache(); 
     } 
     } 
    } 
    return cacheInstance; 
} 

Chúng ta có thực sự cần kiểm tra null 2 ​​cho cacheInstance bên trong khối đồng bộ?

+2

Ngoài câu trả lời, hãy xem c2.com/cgi/wiki?SingletonsAreEvil – Slauster

+0

Bạn có thể muốn đọc bài viết trên Wikipedia về [Khóa kiểm tra kép] (http://en.wikipedia.org/wiki/Double_checked_locking_pattern #Usage_in_Java) –

Trả lời

-1

Có một hàm tạo riêng để tránh tất cả các kiểm tra này.

class Singleton { 
    private static final Singleton instance = new Singleton(); 

    private Singleton() { 
    } 

    public static final Singleton getInstance() { 
     return instance; 
    } 
} 
0

Giả sử cacheInstance được tĩnh bạn nên xem xét hai chiến lược khởi càng tốt:

  • Lazy initilization: Trường singleton là dân cư với một thể hiện vào lúc này khi nó lần đầu tiên được sử dụng (như trong bạn thí dụ).

  • (Standarad) khởi tạo: Trường đơn lẻ được điền với phiên bản ngay sau khi lớp được nạp bởi JVM.

Vì vậy, nếu bạn có ý định sử dụng lệnh khởi động lười, bạn nên kiểm tra tính rỗng, nếu không bạn sẽ chỉ trả về con trỏ rỗng.

Hoặc bạn cũng có thể khởi tạo trường trong một khối tĩnh.

//class declaration 
static { 
    cacheInstance = new DefaultCache(); 
} 

hoặc trong cùng một dòng mà bạn khai báo nó

private static final DefaultCache cacheInstance = new DefaultCache(); 
4

tôi sẽ tránh sự cần thiết của việc kiểm tra tranh chấp sử dụng một singleton uể oải khởi tạo:

public class Singleton { 
    public static ICache getInstance() { 
     return LazyCacheInitializer.INSTANCE; 
    } 

    private class LazyCacheInitializer { 
     private static final ICache INSTANCE = new DefaultCache(); 
    } 
} 
+0

Lợi thế của việc này bằng cách sử dụng 'enum' là gì? –

+0

điều này là đúng – JIV

+1

@Peter Vâng, về bất lợi của enums là mô hình tuần tự hóa của chúng. Enums chỉ tuần tự hóa tên của chúng, nhưng không phải là trạng thái của chúng. Nếu singleton có thể có bất kỳ loại trạng thái nào, nó sẽ bị mất. Như vậy, enums với nhà nước không thể được gửi qua mạng, hoặc lưu và phục hồi từ đĩa. Không chắc chắn nếu nó sẽ là hữu ích để suy nghĩ về serializing bộ nhớ cache singleton trong trường hợp cụ thể này, nhưng câu hỏi của bạn là về một lợi thế/bất lợi. –

6

Bạn cần kiểm tra thứ hai vì giá trị có thể đã được đặt bởi một chuỗi khác trong khi bạn đang cố gắng lấy khóa. Trong thực tế, bạn không có một cái nhìn an toàn về giá trị này cho đến khi bạn đang ở trong khối đồng bộ. Nó có thể đã được thiết lập bởi một chủ đề bất kỳ số lượng thời gian trước đây.

Các singleton lười đơn giản nhất là sử dụng một enum

public enum DefaultCache implements ICache { 
    INSTANCE 
} 

tôi giả sử bạn không làm điều này, do đó bạn có thể thay đổi việc thực hiện.

BTW: Tôi khuyên bạn chỉ nên sử dụng những người độc thân không quốc tịch nếu có thể và sử dụng tiêm phụ thuộc vào tất cả các đối tượng có trạng thái càng nhiều càng tốt.

+0

+1 cho enum (bạn đã nhanh hơn tôi) :) –

1

Có, nếu không, bạn có thể tạo nhiều hơn hai trường hợp. Giả sử bạn có nhiều hơn một chủ đề. Các thử nghiệm đầu tiên được thực hiện với các điều kiện chủng tộc, tức là một số chủ đề xem các biến là null đồng thời và cố gắng thiết lập các ví dụ. Nếu không có kiểm tra thứ hai, mỗi luồng sẽ tạo một cá thể mới.

0

Bạn luôn có thể sử dụng triển khai enum dựa trên mẫu đơn như Peter được đăng nhưng lưu ý rằng tất cả triển khai của bạn là singletons mỗi bộ nạp lớp.

Bạn cũng phải theo dõi giao diện Cloneable.

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