Semaphore应用

275 阅读1分钟

实际应用场景中,连接池创建时设置最大连接数,连接池是怎么控制最多只有最大连接数数量的线程去拿连接对象的呢?

/**
 * 使用信号量实现对象池的限流功能,即同一时刻最多只允许对象池对象数量N的线程数访问对象池
 */
public class ObjectPool {

    final List<Object> pool;
    // 用信号量实现限流器
    final Semaphore sem;

    // 构造函数
    ObjectPool(int size) {
        //vector是线程安全的list
        pool = new Vector<Object>();
        //创建size个对象放入对象池
        for (int i = 0; i < size; i++) {
            pool.add(new Object());
        }
        sem = new Semaphore(size);
    }

    // 利用对象池的对象,调用 func
    @SneakyThrows
    String exec(Function<Object, String> func) {
        Object t = null;
        sem.acquire();
        try {
            t = pool.remove(0);
            return func.apply(t);
        } finally {
            pool.add(t);
            sem.release();
        }
    }

    public static void main(String[] args) {

        // 创建对象池
        ObjectPool pool =new ObjectPool(10);
        // 对象池的对象执行exec(),最多允许size个线程执行func.apply(),多余的线程就阻塞在
        //sem.acquire(),起到限流的作用。
        for (int i = 0; i < 11; i++) {
            new Thread(() -> pool.exec(t -> {
                System.out.println(t);
                return t.toString();
            })).start();
        }
    }
}