本帖最后由 白冥 于 2024-5-31 02:07 编辑
观前科普 单例模式(Singleton Pattern),是一种创建型设计模式,为了保证一个类至始至终都只能有一个唯一实例,即如果你试图实例化这个类,总是只能得到同一个实例对象。 因此,我们私有化这个类的构造方法,并且提供一个公有静态方法充当全局访问点,方便在程序的任何地方都可以且只能通过这唯一一种全局访问点获取这个实例。
为什么我们非要好死不死地控制一个类的实例对象的数量?至于吗?
生活中我们总是会接触到一些共享资源,如共享单车、共享充电宝、共享文件......,资源是共享的,但也是有限的,当一个多个程序访问某一项共享资源时,我们有必要控制这些共享资源的访问权限。在这个例子中,对于客户端,服务端本身就是一个严格的共享资源,如果外界可以肆意创建一个或多个服务端,会造成严重的并发问题。 为什么我们只提供一个唯一的全局访问点?
单例模式让类的唯一实例不可变。在并发编程中,比如函数直接修改、充当参数在函数内部被修改、文件读写、网络通信和打印输出等,任何程序都可能覆盖一个实例对象的原有代码,导致代码难以理解和维护。你不会想让一个问题代码散落在程序各处,竞争条件和不一致状态,增加了并发控制的复杂性。 由于单例模式同时解决了两个问题,所以违背了五个基本设计原则的单一职责原则。 如何使用? 单例模式有两种实现方式,一种称为饿汉式,一种称为懒汉式。 这里给出两种实现方法。 饿汉式 public class Singleton { private static Singleton instance = new Singleton ( ); private Singleton ( ) { } public static Singleton getInstance( ) { return instance; } } 饿汉式的优点是实现方式相对简单,易于理解,获取对象的速度快,且是线程安全的;缺点是如果该类从未被使用,那么其创建的实例就会浪费系统资源。 懒汉式 (非双重检查锁定)
public class Singleton { private static Singleton instance; private Singleton ( ) { } public static Singleton getInstance ( ) { if (instance == null) { instance = new Singleton (); } return instance; } }
懒汉式(非双重检查锁定)的优点是只有在需要使用时才会创建实例,避免了资源的浪费;缺点是在多线程环境下,如果不进行适当的同步,可能会创建多个实例。
懒汉式(双重检查锁定)
public class Singleton { private static Singleton instance; private Singleton ( ) { } public static Singleton getInstance ( ) { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton ( ); } } } return instance; } }
懒汉式(双重检查锁定)的优点是只有在需要使用时才会创建实例,同时减少了不必要的同步开销,避免了资源的浪费;缺点是降低性能,增加了实现的复杂性。 需要注意的是,双重检查锁定在某些旧的Java版本或特定的JVM实现中可能不起作用,因为它依赖于JVM的内存模型。 至于建造者模式,此前已经科普过,这里不再赘述。 使用双重检查锁定(Double-Checked Locking)实现单例模式,确保只有一个CommunicationServer实例在运行。 在私有构造函数中初始化ServerSocket以监听特定端口(默认8080)。 handleConnection方法启动一个线程,不断接受客户端连接,并为每个连接创建一个ClientHandler对象,该对象负责处理与特定客户端的通信。 sendMessageToClient方法允许服务器向指定客户端发送消息。 使用ExecutorService来并发处理客户端连接。 使用ConcurrentHashMap来存储客户端处理程序,以及AtomicInteger来生成唯一的客户端ID,以确保并发安全性。 close方法用于关闭服务器,包括关闭所有客户端连接、停止线程池和清理资源。 客户端连接由ClientHandler类处理,该类实现了消息接收和处理的逻辑。 Message类的所有字段都被声明为final,这意味着一旦Message对象被创建,其状态就不能再改变。这有助于保证数据的完整性和一致性。 Message类用于表示传输的消息,包含发件人、收件人、主题、内容等字段,支持附件,包括附件的名称、大小和文件内容。 在MessageBuilder的setAttachment方法中,从文件读取附件内容并将其作为字节数组存储在消息中。 使用构建器模式来创建Message对象,使代码更易于阅读和维护。 Message类实现了Serializable接口,使其可以通过套接字发送。 |