享元模式指的是可以重复利用之前创建的对象。
比如,Long 的 valueOf
1 2 3 4 5 6 7
| public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { return LongCache.cache[(int)l + offset]; } return new Long(l); }
|
当 l
的值在 -128
到 127
之间的时候,会直接从缓存中返回,而不是创建新的。
案例 自定义连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| package com.redisc;
import lombok.extern.slf4j.Slf4j;
import java.sql.*; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; import java.util.concurrent.atomic.*;
@Slf4j(topic = "c.Test") public class Run {
public static void main(String[] args) throws InterruptedException { Pool pool = new Pool(2); for(int i = 0;i < 5;i++){ new Thread(() -> { Connection connection = pool.borrow(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } pool.free(connection); }).start(); } } }
@Slf4j(topic = "c.Pool") class Pool { // 连接池大小 private final int poolSize; // 连接对象数组 private Connection[] connections;
// 连接状态数组 0 表示空闲 1 表示繁忙 private AtomicIntegerArray states;
//构造方法 public Pool(int poolSize) { this.poolSize = poolSize; this.connections = new Connection[poolSize]; this.states = new AtomicIntegerArray(new int[poolSize]);
for (int i = 0; i < poolSize; i++) { connections[i] = new MockConnection(); } }
// 连接 public Connection borrow() { while (true) { // 获取空闲连接 for (int i = 0; i < poolSize; i++) { if (states.get(i) == 0) { // 弄成线程安全的 if (states.compareAndSet(i, 0, 1)) { log.debug("使用"); return connections[i]; } } } // 如果没有空闲连接,当前线程进入等待 synchronized (this) { try { log.debug("等待"); this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
// 归还链接 public void free(Connection connection) { for (int i = 0; i < poolSize; i++) { if (connections[i] == connection) { log.debug("归还"); states.set(i, 0); synchronized (this) { log.debug("唤醒"); this.notifyAll(); } break; } } } }
class MockConnection implements Connection { ... }
|
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 21:05:21.246 [Thread-1] DEBUG c.Pool - 使用 21:05:21.246 [Thread-0] DEBUG c.Pool - 使用 21:05:21.246 [Thread-2] DEBUG c.Pool - 等待 21:05:21.250 [Thread-4] DEBUG c.Pool - 等待 21:05:21.250 [Thread-3] DEBUG c.Pool - 等待 21:05:22.250 [Thread-1] DEBUG c.Pool - 归还 21:05:22.250 [Thread-0] DEBUG c.Pool - 归还 21:05:22.250 [Thread-0] DEBUG c.Pool - 唤醒 21:05:22.250 [Thread-3] DEBUG c.Pool - 使用 21:05:22.250 [Thread-2] DEBUG c.Pool - 等待 21:05:22.250 [Thread-4] DEBUG c.Pool - 使用 21:05:22.250 [Thread-1] DEBUG c.Pool - 唤醒 21:05:22.250 [Thread-2] DEBUG c.Pool - 等待 21:05:23.253 [Thread-4] DEBUG c.Pool - 归还 21:05:23.253 [Thread-3] DEBUG c.Pool - 归还 21:05:23.253 [Thread-4] DEBUG c.Pool - 唤醒 21:05:23.253 [Thread-2] DEBUG c.Pool - 使用 21:05:23.253 [Thread-3] DEBUG c.Pool - 唤醒 21:05:24.258 [Thread-2] DEBUG c.Pool - 归还 21:05:24.258 [Thread-2] DEBUG c.Pool - 唤醒
|