爱情也能买卖么, 信号量模式(Semaphore Pattern)来摆摊

229 阅读2分钟

目的

保护一组资源中的每个资源都不会受到并发访问而导致不一致

例子代码

男: 砸了你的摊, 逼着你离开, 最后知道真相的我眼泪掉下来, 砸了你的摊, 我背了良心债, 就算付出再多感情也再买不回来

女: 当初是你要分开, 分开就分开, 如今又要用真(政)爱(策), 把我哄回来, 摆摊不是你想摆, 想摆就能摆, 让我挣开, 让我明白, 放手你的爱

摆摊经济一出, 各国人都开启了摆摊之旅:

可是摊位有限, 不能随便摆哦, 我们来讲讲这里面的故事:

我们定义一下货物类:

//商品@Data@AllArgsConstructorpublic class Goods {    private String name;}

定义一个摊位类:

//摊位@Data@AllArgsConstructorpublic class Stall {    private Integer number;    private String name;    private List<Goods> saleGoods;}

定义一个摆摊的人:

//摆摊人@Data@AllArgsConstructorpublic class People {    private String name;    private List<Goods> saleGoods;}

我们三个人同时去摆摊:

List<People> peopleList = new ArrayList<>();peopleList.add(new People("小李", Arrays.asList(new Goods("小李皮鞋"), new Goods("小李运动鞋"))));peopleList.add(new People("小王", Arrays.asList(new Goods("小王西瓜"), new Goods("小王椰子"))));peopleList.add(new People("小张", Arrays.asList(new Goods("小张肥皂"), new Goods("小张洗衣液"))));List<Stall> stallList = new ArrayList<>();stallList.add(new Stall(1,"摊位一",new ArrayList<>()));stallList.add(new Stall(2,"摊位二",new ArrayList<>()));peopleList.parallelStream().forEach(        (people) -> {            for (Stall stall : stallList) {                if(stall.getSaleGoods().isEmpty()) {                    stall.setName(people.getName() + "的摊位");                    //拜访货物中                    putGoods2Stall();                    stall.setSaleGoods(people.getSaleGoods());                }}        });System.out.println(stallList.toString());

输出:

[Stall(number=1, name=小李的摊位, saleGoods=[Goods(name=小李皮鞋), Goods(name=小李运动鞋)]), Stall(number=2, name=小王的摊位, saleGoods=[Goods(name=小张肥皂), Goods(name=小张洗衣液)])]

问题分析

这个和互斥模式是一样的, 主要是状态的不一致, 小王卖了小张的货, 如果用互斥模式来解决也没什么问题, 就是如果对stallList 加锁粒度太大, 并发不高, 如果是对单个摊位加锁, 要注意加锁顺序, 代码也会复杂一些.

信号量模式

List<People> peopleList = new ArrayList<>();peopleList.add(new People("小李", Arrays.asList(new Goods("小李皮鞋"), new Goods("小李运动鞋"))));peopleList.add(new People("小王", Arrays.asList(new Goods("小王西瓜"), new Goods("小王椰子"))));peopleList.add(new People("小张", Arrays.asList(new Goods("小张肥皂"), new Goods("小张洗衣液"))));Semaphore semaphore = new Semaphore(2);peopleList.parallelStream().forEach(        (people) -> {            try {                semaphore.acquire();            } catch (InterruptedException e) {                Thread.currentThread().interrupt();            }            System.out.println(people.getName() + "开始摆摊");            Stall stall = new Stall();            stall.setName(people.getName() + "的摊位");            //摆放货物中            putGoods2Stall();            stall.setSaleGoods(people.getSaleGoods());            System.out.println(LocalDateTime.now() +                                        "" + stall.toString());            semaphore.release();        });

输出:

小王开始摆摊小李开始摆摊2020-06-06T13:04:03.710Stall(number=null, name=小王的摊位, saleGoods=[Goods(name=小王西瓜), Goods(name=小王椰子)])2020-06-06T13:04:03.710Stall(number=null, name=小李的摊位, saleGoods=[Goods(name=小李皮鞋), Goods(name=小李运动鞋)])小张开始摆摊2020-06-06T13:04:05.713Stall(number=null, name=小张的摊位, saleGoods=[Goods(name=小张肥皂), Goods(name=小张洗衣液)])

广告时间:

微信: