【java】单例模式和建造者模式的应用-基于线程池的简易并发通信服务框架
本帖最后由 白冥 于 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的内存模型。static/image/hrline/line4.png至于建造者模式,此前已经科普过,这里不再赘述。static/image/hrline/line4.png代码的全部功能 使用双重检查锁定(Double-Checked Locking)实现单例模式,确保只有一个CommunicationServer实例在运行。 在私有构造函数中初始化ServerSocket以监听特定端口(默认8080)。 handleConnection方法启动一个线程,不断接受客户端连接,并为每个连接创建一个ClientHandler对象,该对象负责处理与特定客户端的通信。 sendMessageToClient方法允许服务器向指定客户端发送消息。 使用ExecutorService来并发处理客户端连接。 使用ConcurrentHashMap来存储客户端处理程序,以及AtomicInteger来生成唯一的客户端ID,以确保并发安全性。 close方法用于关闭服务器,包括关闭所有客户端连接、停止线程池和清理资源。 客户端连接由ClientHandler类处理,该类实现了消息接收和处理的逻辑。 Message类的所有字段都被声明为final,这意味着一旦Message对象被创建,其状态就不能再改变。这有助于保证数据的完整性和一致性。 Message类用于表示传输的消息,包含发件人、收件人、主题、内容等字段,支持附件,包括附件的名称、大小和文件内容。 在MessageBuilder的setAttachment方法中,从文件读取附件内容并将其作为字节数组存储在消息中。 使用构建器模式来创建Message对象,使代码更易于阅读和维护。 Message类实现了Serializable接口,使其可以通过套接字发送。 两种代码用哪种还是看情况而定吧,有各自优点。 很实用的模式惹,看来很多地方都能用到{:6_200:} 代码部分有很多乱码,强烈推荐把代码贴进来的时候使用纯文本模式编辑帖子 仿佛又在上,数据结构的课 哈,完全看不懂,但是感觉又很有用 我的天,看晕了这是可以说的嘛,一点都看不懂 论坛没有专门的程序员,后台的东西好像就是坛花一个人弄,能凑合用就行了吧 看完后的最大感想:呃我的头好痒要长脑子了.jpg{:4_94:} 嗯嗯嗯完全懂了(实际上完全看不懂).jpg 经典八股文,感觉回到了找工作的日子 6,能在泥潭看到java,哈哈哈,楼主是在学java? 啊,头好痒,要长脑子了{:4_91:},重生之我在泥潭学学java 感觉好讲的挺细,可惜我目前的工作还是py和vba用的多一些 用纯文本模式编辑应该能减少一些排版问题,或者代码部分用截图展示之类的。 感觉好厉害,看着就头疼,可恶的Java 想要排版正常用纯文字模式 QAQ 今天也是在论坛涨知识的一天呢。。。 让我想起了在黄色网站讲高数的那个数学老师{:4_114:} 我期待在下面回文看到各种代码大佬的天书回文,拚出美妙的火花...结果没有{:6_167:}
页:
[1]
2