美文网首页
Semaphore信号量使用

Semaphore信号量使用

作者: 奇点一氪 | 来源:发表于2019-11-28 09:07 被阅读0次

    Semaphore是什么

    信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程能够正确、合理的使用公共资源。信号量维护了一个许可集,在初始化Semaphore为许可集传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。

    线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成,"许可"将被归还给Semaphore。

    类结构

    如下图所示,与ReentrantLock一样基于AQS的子类Sync并有公平和非公平模式。Sync继承自AQS,而NonfairSync和FairSync继承自Sync。



    再回顾下AQS提供的模板方法:

    //独占模式
    protected boolean tryAcquire(int arg);
    protected boolean tryRelease(int arg);
    //共享模式
    protected int tryAcquireShared(int arg);
    protected boolean tryReleaseShared(int arg);
    //判断当前线程是否排它持有state
    protected boolean isHeldExclusively();
    

    代码演示

    package com.learn.wecath.thread;
    
    import java.util.Date;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class SemaphoreDemo {
    
        //用static 和final 这样就表明属于类级别的,既然是类级别的,那么可以认为是单例模式的
        //也就是最大的并发访问量是3个,即同一时间
        //构造参数:
        /**
         * 1.默认是非公平的,因为里面包含的是一个队列,要实现公平策略,初始化的时候,通过构造函数设置为true,即满足FIFO的原则
         * 2.实现单例模式:
         * 将Semaphore semaphore = new Semaphore(1),即满足单例模式
         */
        private static final Semaphore          semaphore  = new Semaphore(3);
        //并发访问的线程数3个
        //创建5个线程,利用线程池,因为创建完线程池,线程的启动即submit()或者execute()就是任务提交和线程启动的一个过程
        private static       ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
    
        //静态内部类
        private static class InformationThread extends Thread {
            //本身是一个普通类,当继承了Thread类之后,就变成一个任务类,即异步处理的类当然他也有自己本身的属性
            private final String name;
            private final int    age;
    
            private InformationThread(String name, int age) {
                this.name = name;
                this.age = age;
            }
    
            @Override
            public void run() {
                try {
                    /**
                     * 通过源码发现:
                     * acquire有两个方法类型:
                     * 一个是带参的,限制了获取共享资源的线程数
                     * 一个是不带参的,没有限制
                     * 当然是用在run方法中.
                     */
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + ":大家好,我是" + name + "我今年" + age + "岁当前时间为:" + System.currentTimeMillis());
                    Thread.sleep(1000);
                    System.out.println(name + "要准备释放许可证了,当前时间为:" + new Date());
                    System.out.println("当前可使用的许可数为:" + semaphore.availablePermits());
                    semaphore.release();
                } catch (Exception e) {
                    e.getMessage();
                }
            }
        }
    
        public static void main(String[] args) {
            String[] name = {"李明", "王五", "张杰", "王强", "赵二", "李四", "张三"};
            int[] age = {26, 27, 33, 45, 19, 23, 41};
            for (int i = 0; i < 7; i++) {
                //创建一个对象的形式;
                /**
                 * 1.利用多态的形式创建---即对象的引用(instanceof)
                 * 2.利用对象本身创建
                 */
                Thread thread = new InformationThread(name[i], age[i]);
                threadPool.execute(thread);
            }
        }
    
    
    }
    
    
    

    相关文章

      网友评论

          本文标题:Semaphore信号量使用

          本文链接:https://www.haomeiwen.com/subject/jgnpwctx.html