享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。该模式主要用于解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
    image.png
    image.png

    比如,池化技术就是一种享元模式的应用,比如下面的自定义线程池:

    1. @Slf4j(topic = "c.Pool")
    2. public class Pool {
    3. // 1. 连接池大小
    4. private final int poolSize;
    5. // 2. 连接对象数组
    6. private final Connection[] connections;
    7. // 3. 连接状态数组 0 表示空闲, 1 表示繁忙
    8. private final AtomicIntegerArray states;
    9. // 4. 构造方法初始化
    10. public Pool(int poolSize) {
    11. this.poolSize = poolSize;
    12. this.connections = new Connection[poolSize];
    13. this.states = new AtomicIntegerArray(new int[poolSize]);
    14. for (int i = 0; i < poolSize; i++) {
    15. connections[i] = new MockConnection("连接" + (i + 1));
    16. }
    17. }
    18. // 5. 借连接
    19. public Connection borrow() {
    20. while (true) {
    21. for (int i = 0; i < poolSize; i++) {
    22. // 获取空闲连接
    23. if (states.get(i) == 0) {
    24. //CAS操作,线程安全
    25. if (states.compareAndSet(i, 0, 1)) {
    26. log.debug("borrow {}", connections[i]);
    27. return connections[i];
    28. }
    29. }
    30. }
    31. // 如果没有空闲连接,当前线程进入等待
    32. synchronized (this) {
    33. try {
    34. log.debug("wait...");
    35. this.wait();
    36. } catch (InterruptedException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. }
    42. // 6. 归还连接
    43. public void free(Connection conn) {
    44. for (int i = 0; i < poolSize; i++) {
    45. if (connections[i] == conn) {
    46. states.set(i, 0);
    47. synchronized (this) {
    48. log.debug("free {}", conn);
    49. this.notifyAll();
    50. }
    51. break;
    52. }
    53. }
    54. }
    55. public static void main(String[] args) {
    56. Pool pool = new Pool(2);
    57. for (int i = 0; i < 5; i++) {
    58. new Thread(() -> {
    59. Connection conn = pool.borrow();
    60. try {
    61. Thread.sleep(new Random().nextInt(1000));
    62. } catch (InterruptedException e) {
    63. e.printStackTrace();
    64. }
    65. pool.free(conn);
    66. }).start();
    67. }
    68. }
    69. }
    70. class MockConnection implements Connection {
    71. // 实现略
    72. }

    运行结果:
    image.png