JUC-java并发编程-并发工具类-Semaphore(1)

7 篇文章 0 订阅

JUC

Semaphore

信号量,用来限制能同时访问共享资源的线程上限(单机限流)。单位时间内,只允许 设定数量的线程执行,超过数量的线程进入阻塞。等到执行中线程调用release()释放了资源,阻塞线程竞争资源继续执行。

Semaphore可以设置公平与非公平两种模式(默认非公平的),非公平模式在竞争Sempahore资源的时候不会判断等待队列是否有线程阻塞,公平模式则在acquire()方法中先判断等待队列中是否有阻塞线程,存在则排队到队列中。

使用例子:

public class SemaphoreTest {
    public static void main(String[] args) {
        //创建Semaphore对象
        Semaphore semaphore = new Semaphore(3);

        for(int i=0;i<10;i++){
            new Thread(()->{
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    log.info("running...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.info("end...");
                } finally {
                    semaphore.release();
                }
            }).start();
        }
    }
}

结果打印:

14:01:19.480 [Thread-1] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:19.480 [Thread-0] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:19.480 [Thread-2] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:20.498 [Thread-0] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:20.498 [Thread-1] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:20.498 [Thread-2] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:20.498 [Thread-4] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:20.498 [Thread-3] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:20.498 [Thread-5] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:21.509 [Thread-4] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:21.509 [Thread-3] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:21.509 [Thread-5] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:21.509 [Thread-6] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:21.509 [Thread-8] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:21.509 [Thread-7] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:22.521 [Thread-6] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:22.521 [Thread-7] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:22.521 [Thread-8] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…
14:01:22.521 [Thread-9] INFO jl.com.jl.juc.semaphore.SemaphoreTest - running…
14:01:23.534 [Thread-9] INFO jl.com.jl.juc.semaphore.SemaphoreTest - end…

Semaphore的应用

1.使用Semaphore限流,在访问高峰期时,让请求线程阻塞,高峰期过去再释放许可,当然它只适合限制单机线程数量,兵器仅是限制线程数,而不是限制资源数(例如连接数,对比Tomcat LimitLatch的实现-这个我还没有看。。。后续要恶补了)

2.用Semaphore实现简单连接池,对比享元模式下的实现(用 wait notify实现),性能和可读性显然更好,

/**
 * 通过sempahore 优化数据库连接池
 * @author jiangl
 * @version 1.0
 * @date 2021/4/15 11:03
 */
public class SemaphorePoolTest {
    public static void main(String[] args) {
        MyPool myPool = new MyPool(2);
        List<Thread> lists = new ArrayList<>();
        for(int i=0;i<10;i++){
            lists.add(new Thread(()->{
                Connection borrow = myPool.borrow();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myPool.release(borrow);
            }));
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0;i<10;i++){
            lists.get(i).start();
        }
    }
}

@Slf4j(topic = "my.MyPool")
class MyPool{
    /**
     * 连接池大小
     */
    private final int poolSize;

    /**
     * 链接数组
     */
    private Connection[] connections;

    /**
     * 链接状态数组
     */
    private AtomicIntegerArray statesArray;

    private Semaphore semaphore;

    /**
     * 连接池对象构造方法
     * @param poolSize
     */
    public MyPool(int poolSize) {
        this.poolSize = poolSize;
        this.semaphore = new Semaphore(poolSize);
        this.connections = new Connection[poolSize];
        this.statesArray = new AtomicIntegerArray(poolSize);
        for(int i=0;i<poolSize;i++){
            this.connections[i] = new MyConnection();
            this.statesArray.set(i,0);
        }
    }

    /**
     *
     * @return
     */
    public Connection borrow(){
        //获取许可
        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0;i<poolSize;i++){
            if(statesArray.get(i) == 0){
                if (statesArray.compareAndSet(i,0,1)) {
                    log.info("borrow {}",connections[i]);
                    return this.connections[i];
                }
            }
        }
        //不会执行到这里
        return null;
    }

    /**
     * 释放链接
     * @param connection
     */
    public void release(Connection connection){
        for(int i=0;i<poolSize;i++){
            if(connections[i] == connection){
                statesArray.set(i,0);
                log.info("free {}",connection);
                semaphore.release();
                break;
            }
        }

    }


}


class MyConnection implements Connection{
	//省略。。。 只是实现了Connection的空方法,没有实际逻辑
}

执行结果:

14:11:43.111 [Thread-0] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:43.111 [Thread-1] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:43.621 [Thread-1] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:43.621 [Thread-0] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:43.621 [Thread-2] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:43.621 [Thread-3] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:44.133 [Thread-3] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:44.133 [Thread-2] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:44.133 [Thread-4] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:44.133 [Thread-5] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:44.634 [Thread-5] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:44.634 [Thread-4] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:44.634 [Thread-7] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:44.634 [Thread-6] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:45.134 [Thread-7] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:45.134 [Thread-6] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:45.134 [Thread-9] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:45.134 [Thread-8] INFO my.MyPool - borrow com.jl.juc.semaphore.MyConnection@52a62ac5
14:11:45.648 [Thread-9] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@53df8f5b
14:11:45.648 [Thread-8] INFO my.MyPool - free com.jl.juc.semaphore.MyConnection@52a62ac5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值