• 基于享元模式实现连接池


    享元模式

    结构

    享元(Flyweight )模式中存在以下两种状态:

    1. 内部状态,即不会随着环境的改变而改变的可共享部分。

    2. 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两 种状态,并将外部状态外部化。

    享元模式的主要有以下角色:

    抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公 共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法 来设置外部数据(外部状态)。

    具体享元(Concrete Flyweight)角色 :它实现了抽象享元类,称为享元对象;在具体享元 类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享 元类提供唯一的享元对象。

    非享元(Unsharable Flyweight)角色 :并不是所有的抽象享元类的子类都需要被共享,不 能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过 实例化创建。

    享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元 对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在 的话,则创建一个新的享元对象。

    优缺点

    优点:

    • 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能
    • 享元模式中的外部状态相对独立,且不影响内部状态

    缺点:

    为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂

    适用场景:

    • 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
    • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
    • 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应 当在需要多次重复使用享元对象时才值得使用享元模式。
    1. public class Pool {
    2. //1. 连接池大小
    3. private final int poolSize;
    4. //2. 连接对象数组
    5. private Connection[] connections;
    6. //3. 连接池状态数组 0空闲 1繁忙 因为要多线程修改,所以要保证线程安全
    7. private AtomicIntegerArray states;
    8. public Pool(int poolSize){
    9. this.poolSize = poolSize;
    10. this.connections = new Connection[poolSize];
    11. this.states = new AtomicIntegerArray(new int[poolSize]);
    12. for (int i = 0; i < poolSize; i++) {
    13. //MockConnection 实现于 Connection
    14. connections[i] = new MockConnection();
    15. }
    16. }
    17. //借连接
    18. public Connection borrow(){
    19. while(true){
    20. for (int i = 0; i < poolSize; i++) {
    21. //获取空闲连接
    22. if(states.get(i) == 0){
    23. if(states.compareAndSet(i,0,1)){
    24. System.out.println("borrow:"+connections[i]);
    25. return connections[i];
    26. }
    27. }
    28. }
    29. // 如果没有空闲连接,当前线程进入等待
    30. synchronized (this){
    31. try {
    32. this.wait();
    33. } catch (InterruptedException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. }
    38. }
    39. //归还连接
    40. public void free(Connection conn){
    41. for(int i = 0;i < poolSize;i++){
    42. if(connections[i] == conn){
    43. states.set(i,0);
    44. synchronized (this){
    45. System.out.println("free:"+conn);
    46. this.notifyAll();
    47. }
    48. break;
    49. }
    50. }
    51. }
    52. public static void main(String[] args) {
    53. Pool pool = new Pool(2);
    54. for (int i = 0; i < 5; i++) {
    55. new Thread( ()->{
    56. Connection conn = pool.borrow();
    57. try {
    58. Thread.sleep(new Random().nextInt(1000));
    59. } catch (InterruptedException e) {
    60. e.printStackTrace();
    61. }
    62. pool.free(conn);
    63. }).start();
    64. }
    65. }
    66. }

  • 相关阅读:
    Docker快速搭建Drupal内容管理系统并远程访问
    最新整理源码面试题
    如何修复Power BI【View usage metrics report】指标报表数据源更新问题?
    文件管理系统----文件目录
    关于org.tio.core.udp的UDP交互使用示例
    iOS蓝牙 Connection Parameters 关键参数说明
    Vue收集表单数据
    操作系统·操作系统引论
    张鑫溢:9.12国际金价上涨,并有望时隔三周重新收涨?黄金原油独家操作建议指导.
    再出发感怀
  • 原文地址:https://blog.csdn.net/weixin_53390884/article/details/138139591