线程阻塞(二),Semaphore介绍

上一篇介绍了CountDownLatch和CyclicBarrier的使用,本篇介绍下另外一个阻塞工具Semaphore,有点类似CountDownLatch和CyclicBarrier,它也能实现线程阻塞,也能计数,但是更像是一种线程调度,具体看一下使用方法吧。

构造方法

    public Semaphore(int permits) {//permits代表最多允许多少个线程同时访问
        sync = new NonfairSync(permits);
    }
    public Semaphore(int permits, boolean fair) {// fail表示是否公平,先等待的优先
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

它有几个主要的方法

public void acquire() throws InterruptedException {  }     //获取一个许可
public void acquire(int permits) throws InterruptedException { }    //获取permits个许可
public void release() { }          //释放一个许可
public void release(int permits) { }    //释放permits个许可

使用的时候,先调用acquire()获取许可,如果当前没有可用的许可,则一直等待,直到有可用的许可。

1、简单用法

比如笔者现在到饭点了,假如说公司食堂有5个座位,公司有8个人,这样的话同时最多支持5个人就餐,那剩下的人只能等着,有人吃完饭后,让出座位,让其他人吃饭。

public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5);// 总共有5个座位
        for (int i = 0; i < 8; i++) {// 总共有8个人需要吃饭
            People people = new People(semaphore, i);
            people.start();
        }
    }

    static class People extends Thread {
        Semaphore semaphore;
        int id;

        public People(Semaphore semaphore, int id) {
            this.semaphore = semaphore;
            this.id = id;
        }

        @Override
        public void run() {
            try {
                this.semaphore.acquire();
                System.out.println("have dinner begin " + id);
                sleep((long) (Math.random() * 5000));//模拟线程耗时各不不同
                System.out.println("have dinner end ****" + id);
                this.semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

执行结果:

have dinner begin 0
have dinner begin 3
have dinner begin 4
have dinner begin 2
have dinner begin 1
have dinner end ****0
have dinner begin 5
have dinner end ****1
have dinner begin 6
have dinner end ****3
have dinner begin 7
have dinner end ****6
have dinner end ****4
have dinner end ****2
have dinner end ****7
have dinner end ****5

这样,只要有线程让出资源,立马就有线程补上去。

2、需要多个资源

当调用acquire(int permits)方法,permits>1的时候,就是需要一次占用多个资源,比如上面的demo,如果是线程内部是这样:

                this.semaphore.acquire(5);
                System.out.println("have dinner begin " + id);
                sleep((long) (Math.random() * 5000));// 模拟线程耗时各不不同
                System.out.println("have dinner end ****" + id);
                this.semaphore.release(5);

执行结果:

have dinner begin 0
have dinner end ****0
have dinner begin 1
have dinner end ****1
have dinner begin 2
have dinner end ****2
have dinner begin 3
have dinner end ****3
have dinner begin 4
have dinner end ****4
have dinner begin 5
...

可能有的人比较胖,一次占了5个座位(餐厅座位是有多小啊),这样一次只能有一个人吃饭了。

3、acquire(int permits)和release(int permits)不一样

3.1 release个数大于acquire个数

                this.semaphore.acquire(1);
                System.out.println("have dinner begin " + id);
                sleep((long) (Math.random() * 5000));// 模拟线程耗时各不不同
                System.out.println("have dinner end ****" + id);
                this.semaphore.release(3);
                System.out.println("可用的座位数:" + this.semaphore.availablePermits());

执行结果:

have dinner begin 0
have dinner begin 3
have dinner begin 2
have dinner begin 1
have dinner begin 4
have dinner end ****0
可用的座位数:3
have dinner begin 5
have dinner begin 7
have dinner begin 6
have dinner end ****3
可用的座位数:3
have dinner end ****5
可用的座位数:6
have dinner end ****1
可用的座位数:9
have dinner end ****4
可用的座位数:12
have dinner end ****7
可用的座位数:15
have dinner end ****2
可用的座位数:18
have dinner end ****6
可用的座位数:21

最终又扩容了,本来是8个座位,最后每个人吃完饭走的时候,释放了自己的座位,又多创造了2个座位,最终变成21个座位了
3.2 release个数小于acquire个数

                this.semaphore.acquire(3);
                System.out.println("have dinner begin " + id);
                sleep((long) (Math.random() * 5000));// 模拟线程耗时各不不同
                System.out.println("have dinner end ****" + id);
                this.semaphore.release(1);
                System.out.println("可用的座位数:" + this.semaphore.availablePermits());

执行结果:


由于每次占用3个座位,用完后,释放一个座位,另外2个座位本来不用了,但是没有释放,那么别人也用不了,造成资源浪费,同时也影响往下执行。

总结:
Semaphore能锁住资源,比较适合在资源固定,使用者较多的时候,也就是僧多粥少的情况下使用,另外,acquire个数和release个数最好一致。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

  • 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,Cycl...
    Pure_Dream阅读 1,425评论 0 3
  • 告别了漫长而暴躁的考试周,总归不用一天好几包巧克力的度过,日子过的啊,说充实也充实,说空虚,也不算过分。 回家了之...
    西有葳蕤阅读 235评论 0 0
  • ——CNS打卡群9月份线下活动 群里的各位小伙伴,咱们的前两次线下活动呢,第一次,是吃,第二次,还是吃。所以,这一...
    无言的白茶阅读 320评论 0 0
  • 昨天晚上哦不应该是今天了,加班学习到两点多才睡,今早还能坚持给我做早餐,我迷迷糊糊醒来时正在阳台晒衣服,跟往常一样...
    第十四行阅读 156评论 0 0