Tìm hiểu Singleton trong Java

Ngày đăng: 11/06/2020   -    Cập nhật: 11/06/2020

Trong bài viết này mình sẽ hướng dẫn bạn tìm hiểu về Singleton trong Java. Hiểu về một Design Pattern để từng bước nâng cao Level của mình.

 

Singleton trong Java

Singleton trong Java

 

Sau một thời gian mặn mà với Java cơ bản, bất cứ ai cũng muốn nâng cấp kiến thức của mình lên một nấc thang mới.


Và đây cũng là quy luật tất yếu để trở thành một lập trình viên thực sự. Không ai chịu ngồi lại mãi với những thứ cơ bản hoài được đúng không?


Nhưng phần nâng cao trong Java không hề ít, không thể hoặc cũng khó mà chia sẻ được hết trong một sớm một chiều được.


Do đó, trong bài viết này, mình cùng nhau học, cùng nhau chia sẻ về Singleton trong Java nhé.



1. Singleton trong Java là gì?
 

 

Singleton là 1 trong 6 Design Pattern của nhóm Creational Design Pattern, đảm bảo chỉ duy nhất một thể hiện (instance) được tạo ra và nó sẽ cung cấp cho bạn một method để có thể truy xuất được thể hiện duy nhất đó mọi lúc mọi nơi trong chương trình.

 

Singleton thường được sử dụng trong logger, configuration, cache,… Cache là một ví dụ cũng hay sử dụng.


Ví dụ chúng ta rất hay sử dụng instance A() của class A nào đó, tuy nhiên việc khởi tạo lớp A rất tốn kém, chúng ta có thể dùng một class singleton ProvideA để tạo A một lần và share A.


Việc này sẽ hiệu quả hơn rất nhiều khi tạo nhiều instance của A.



2. Cách sử dụng / ứng dụng singleton trong Java


 

Singleton trong Java dường như là một trong 25 loại Design Pattern đơn giản và dễ sử dụng nhất. Tuy nhiên, khi làm việc với Singleton nó đi kèm với nhiều mối liên hệ ta cần phải bận tâm đến.

 

Để triển khai một Singleton, có nhiều cách tiếp cận khác nhau nhưng tất cả chúng đều có các đặc điểm chung sau đây.

 

  • Hàm tạo riêng để hạn chế khởi tạo lớp từ các lớp khác.

  • Biến static riêng của cùng một lớp là duy nhất.

  • Phương thức static công khai trả về thể hiện của lớp, đây là điểm truy cập toàn cục cho lớp bên ngoài để lấy thể hiện của lớp Singleton.



Trong các phần tiếp theo, chúng ta sẽ tìm hiểu các cách tiếp cận khác nhau về Singleton và mối quan tâm thiết kế tới việc triển khai đó.

 

Eager initialization


 

Trong Eager initialization, thể hiện của Singleton Class được tạo tại thời điểm tải lớp.


Đây là phương pháp dễ nhất để tạo một lớp Singleton trong Java.


Nhưng nó có một nhược điểm là thể hiện đó được tạo ra mặc dù ứng dụng khách có thể không sử dụng nó.


 


package singleton;

public class EagerInitialization {

    private static final EagerInitialization instance = new EagerInitialization();
    // hàm constructor để tránh các client-application sử dụng
    private EagerInitialization() {
    }
    public static EagerInitialization getInstance() {
        return instance;
    }

}
 

 

Static block initialization


 

Triển khai khởi tạo Static block tương tự như Eager initialization, ngoại trừ trường hợp lớp được tạo trong khối static cung cấp tùy chọn để xử lý ngoại lệ.

 


package singleton;

public class StaticBlock {
    private static StaticBlock instance;
    private StaticBlock() {
    }
    // tạo khối static để xử lý ngoai lệ
    static {
        try {
            instance = new StaticBlock();
        } catch (Exception e) {
            throw new RuntimeException("Có ngoại lệ xảy ra");
        }
    }
    public static StaticBlock getInstance() {
        return instance;
    }
}
 

 

Lazy Initialization


 

Phương thức này tạo ra một thể hiện có thể truy cập toàn cục.


Việc triển khai phương thức này hoạt động tốt trong trường hợp môi trường đơn luồng nhưng khi đối với các hệ thống đa luồng, nó có thể gây ra sự cố nếu nhiều luồng nằm trong điều kiện if cùng một lúc.


Nó sẽ phá hủy mẫu singleton và cả hai luồng sẽ nhận được các thể hiện khác nhau của lớp singleton.


 


package singleton;


public class LazyInitialization {

    private static LazyInitialization instance;
    private LazyInitialization() {
    }
    public static LazyInitialization getInstance() {
        if (instance == null) {
            instance = new LazyInitialization();
        }
        return instance;
    }
}
 


Thread Safe Singleton
 


 

Cách dễ dàng hơn để tạo một lớp Thread Safe Singleton là làm cho phương thức truy cập toàn cục được đồng bộ hóa, để chỉ một luồng có thể thực thi phương thức này tại một thời điểm.


Việc triển khai này hoạt động tốt và cung cấp sự an toàn của luồng nhưng nó làm giảm hiệu suất do chi phí liên quan đến phương thức được đồng bộ hóa.

 



package singleton;

public class ThreadSafe {

    private static ThreadSafe instance;
    private ThreadSafe() {
    }
    public static synchronized ThreadSafe getInstance() {
        if (instance == null) {
            instance = new ThreadSafe();
        }
        return instance;
    }
}
 

Bill Pugh Singleton Implementation


 

Đây là cách tiếp cận được sử dụng rộng rãi nhất cho lớp Singleton vì nó không yêu cầu đồng bộ hóa.
 


package singleton;

public class BillPugh {

    private BillPugh() {
    }
    private static class SingletonHelper {
        private static final BillPugh INSTANCE = new BillPugh();
    }
    public static BillPugh getInstance() {
        return SingletonHelper.INSTANCE;
    }
}
 


Sử dụng Reflection để phá hủy mô hình Singleton


 

Khi bạn chạy code bên dưới, bạn sẽ thấy rằng hashCode của cả hai trường hợp không giống nhau sẽ phá hủy singleton.


Reflection rất mạnh mẽ và được sử dụng trong rất nhiều framework như Spring và Hibernate.


 


package singleton;
import java.lang.reflect.Constructor;

public class Reflection {

    public static void main(String[] args) {

        EagerInitialization instanceOne = EagerInitialization.getInstance();
        EagerInitialization instanceTwo = null;

        try {
            Constructor[] constructors = EagerInitialization.class.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                // Below code will destroy the singleton pattern
                constructor.setAccessible(true);
                instanceTwo = (EagerInitialization) constructor.newInstance();
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(instanceOne.hashCode());
        System.out.println(instanceTwo.hashCode());
    }
}
 


Enum Singleton


 

Ra đời để khắc phục các tình trạng của Reflection, mọi giá trị enum chỉ được khởi tạo một lần và  các giá trị Java Enum có thể truy cập được trên toàn cục, nên Singleton cũng vậy. Hạn chế là Enum có phần không linh hoạt.

 


package singleton;

public enum EnumSingleton {
    INSTANCE;
    public static void doSomething() {
        // làm gì đó
    }
}
 


Serialization and Singleton


 

Phương thức này để lưu trữ trạng thái trong hệ thống và truy xuất nhằm nối tiếp các Singleton trong quá trình triển khai các interface đối với các hệ thống phân tán.

 


package singleton;
import java.io.Serializable;

public class Serialization implements Serializable {

    private static final long serialVersionUID = -7604766932017737115L;
    private Serialization() {}

    private static class SingletonHelper {
        private static final Serialization instance = new Serialization();
    }

    public static Serialization getInstance() {
        return SingletonHelper.instance;
    }
}
 


Có rất nhiều cách implement cho Singleton, mỗi cách có ưu – nhược điểm khác nhau. Tùy theo trường hợp cụ thể, bạn có thể chọn cho mình cách implement phù hợp nhất.



3. Kết luận



Nếu chỉ lướt sơ qua thôi thì Singleton trong Java khá phức tạp và không biết đâu mà dùng. Nhưng nếu bạn đã học qua các kiến thức cơ bản của Java thì nó không qua khó, thậm chỉ dễ hiểu – vì singleton trong Java được xem như là Pattern dễ.

 

Design Pattern nói chung và Singleton nói riêng đóng vai trò quan trọng trong cách tổ chức và thực thi chương trình, bạn sẽ không thấy trong mấy bài cơ bản đâu, chỉ những dự án lớn, cần nhiều tài nguyên và cần tối ưu hoá mới dùng đến Singleton và các Design Pattern khác.


Biết Singleton sẽ giúp bạn phần nào trở thành lập trình viên Java “khác so với phần còn lại” và nâng cao phần nào giá trị của mình trong mắt bạn bè đồng nghiệp.


 

> Tham khảo: Khóa học Java Web (6 tháng đồng hành cùng chuyên gia doanh nghiệp). Tất cả những thứ cần thiết để làm việc với Java sẽ được dạy trong khóa học này.


 

Còn nếu bạn tự học Java thì cũng nên cân nhắc tiếp xúc với Singleton trong Java và các Design Pattern khác sau khi đã Học Java cơ bản được kha khá, tránh bị sốc và hoang mang khi vấp phải những dòng code nâng cao - phức tạp.
 

> Đọc thêm: NullPointerException trong Java



---

HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Dạy học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543 - 0353655150 
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #python #java #php
Bình luận Facebook
Mục lục
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!