java双端队列原理(初学者java入门基础知识)

队列(Queue):与栈相对的一种数据结构,集合(Collection)的一个子类。队列允许在一端进行插入操作,而在另一端进行删除操作的线性表,栈的特点是后进先出,而队列的特点是先进先出。队列的用处很大,比如实现消息队列。Queue类关系图,如下图所示: 注:为了让读者更直观地理解,上图为精简版的Queue类关系图。本文如无特殊说明,内容都是基于Java1.8版本。 队列(Queue) 1)Que…

队列(Queue):与栈相对性的一种算法设计, 结合(Collection)的一个派生类。队列容许在一端开展插进实际操作,而在另一端开展移除使用的线性表,栈的特性是后进先出,而队列的特点是先进先出法。队列的用途非常大,例如完成信息队列。Queue 类关系图,如下图所示:

如何手撸一个Java队列?队列详解和面试题汇总(含答案)

注:为了更好地让大家更直接地了解,图中为精简的 Queue 类关系图。文中如无特别表明,內容是根据 Java 1.8 版本号。

队列(Queue)

1)Queue 归类

从图中可以看得出 Queue 大致可分成下列三类。

  1. 二端队列:双端队列(Deque)是 Queue 的派生类也是 Queue 的填补类,头顶部和尾端都适用元素插进和获得。
  2. 堵塞队列:阻塞队列指的是在元素实际操作时(加上或删掉),要是没有取得成功,会堵塞等候实行。例如,当加上元素时,假如队列元素已满,队列会堵塞等候直到有位置时再插进。
  3. 非堵塞队列:非阻塞队列和堵塞队列反过来,会立即返回实际操作的結果,并非堵塞等候。二端队列也是非堵塞队列。

2)Queue 方式表明

Queue 常见方式,如下图所示:

如何手撸一个Java队列?队列详解和面试题汇总(含答案)

方法表明:

  • add(E):加上元素到队列尾端,取得成功返回 true,队列超过时抛出异常;
  • offer(E):加上元素到队列尾端,取得成功返回 true,队列超过时返回 false;
  • remove():删掉元素,取得成功返回 true,不成功返回 false;
  • poll():获得并清除此队列的第一个元素,若队列为空,则返回 null;
  • peek():获得但不清除此队列的第一个元素,若队列为空,则返回 null;
  • element():获得但不清除此队列的第一个元素,若队列为空,则抛出现异常。

3)Queue 应用案例

Queue<String> linkedList = new LinkedList<>();
linkedList.add(\"Dog\");
linkedList.add(\"Camel\");
linkedList.add(\"Cat\");
while (!linkedList.isEmpty()) {
  System.out.println(linkedList.poll());
}

程序运行結果:

Dog

Camel

Cat

堵塞队列

1)BlockingQueue

BlockingQueue 在 java.util.concurrent 包下,别的堵塞类都完成自 BlockingQueue 插口,BlockingQueue 给予了线程安全的队列浏览方法,当向队列中插进数据信息时,假如队列已满,进程则会堵塞等候队列中元素被取下后再插进;当从队列中取数据信息时,假如队列为空,则进程会堵塞等候队列中有新元素再获得。BlockingQueue 关键方式插入方法:

  • add(E):加上元素到队列尾端,取得成功返回 true,队列超过时抛出异常;
  • offer(E):加上元素到队列尾端,取得成功返回 true,队列超过时返回 false ;
  • put(E):将元素插进到队列的尾端,假如该队列已满,则一直堵塞。

删掉方式:

  • remove(Object):清除特定元素,取得成功返回 true,不成功返回 false;
  • poll(): 获得并清除队列的第一个元素,假如队列为空,则返回 null;
  • take():获得并清除队列第一个元素,要是没有元素则一直堵塞。

查验方式:

  • peek():获得但不清除队列的第一个元素,若队列为空,则返回 null。

2)LinkedBlockingQueue

LinkedBlockingQueue 是一个由单链表完成的有限堵塞队列,容积初始值为 Integer.MAX_VALUE,还可以自定容积,提议特定容积尺寸,默认设置尺寸在加上速率超过删掉速率状况下有导致内存溢出的风险性,LinkedBlockingQueue 是先进先出法的形式储存元素。

3)ArrayBlockingQueue

ArrayBlockingQueue 是一个有界限的堵塞队列,它的里面完成是一个二维数组。它的存储容量是有局限的,大家一定在其复位的情况下特定它的容积尺寸,容积尺寸一旦特定就不能更改。ArrayBlockingQueue 也是先进先出法的形式存放数据信息,ArrayBlockingQueue 内部结构的堵塞队列是根据再入锁 ReenterLock 和 Condition 标准队列完成的,因而 ArrayBlockingQueue 中的元素存有公平公正浏览和非公平公正浏览的差别,针对公平公正浏览队列,被堵塞的进程可以依照堵塞的顺序浏览队列,即先堵塞的进程先浏览队列。并非公平公正队列,当队列可以用时,堵塞的进程将进到角逐浏览資源的市场竞争中,换句话说谁先抢得谁就实行,沒有稳固的顺序。实例编码如下所示:

// 默认设置非公平公正堵塞队列
ArrayBlockingQueue queue = new ArrayBlockingQueue(6);
// 公平公正堵塞队列
ArrayBlockingQueue queue2 = new ArrayBlockingQueue(6,true);
// ArrayBlockingQueue 源代码展现
public ArrayBlockingQueue(int capacity) {    
  this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
  if (capacity <= 0) 
    throw new IllegalArgumentException();    
  this.items = new Object[capacity]; 
  lock = new ReentrantLock(fair); 
  notEmpty = lock.newCondition();  
  notFull =  lock.newCondition();}

4)DelayQueue

DelayQueue 是一个适用延迟获得元素的无边堵塞队列,队列中的元素务必完成 Delayed 插口,在建立元素时可以特定时间延迟,仅有抵达了延时的时间段以后,才可以得到到该元素。完成了 Delayed 插口务必重新写过2个方式 ,getDelay(TimeUnit) 和 compareTo(Delayed),如下所示编码所显示:

class DelayElement implements Delayed { 
  @Override        // 获得剩下的时间       
  public long getDelay(TimeUnit unit) {
    // do something       
  }
  @Override        // 队列里元素的排列根据
  public int compareTo(Delayed o) {            // do something 
  }  
}

DelayQueue 应用的详细实例,请参照下列编码:

public class DelayTest { 
  public static void main(String[] args) throws InterruptedException {  
    DelayQueue delayQueue = new DelayQueue(); 
    delayQueue.put(new DelayElement(1000));
    delayQueue.put(new DelayElement(3000)); 
    delayQueue.put(new DelayElement(5000)); 
    System.out.println(\"开始时间:\"    DateFormat.getDateTimeInstance().format(new Date())); 
    while (!delayQueue.isEmpty()){
      System.out.println(delayQueue.take());
    } 
    System.out.println(\"完毕時间:\"    DateFormat.getDateTimeInstance().format(new Date())); 
  } 
static class DelayElement implements Delayed {        // 延迟时间截止时间(单层:ms)
  long delayTime = System.currentTimeMillis(); 
public DelayElement(long delayTime) { 
  this.delayTime = (this.delayTime   delayTime); 
} 
@Override        // 获得剩下的时间 
public long getDelay(TimeUnit unit) {
  return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 
} 
@Override        // 队列里元素的排列根据 
public int compareTo(Delayed o) { 
  if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) { 
    return 1;
  } else if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) { 
    return -1;  
  } else {      
    return 0;      
  }   
}      
@Override      
public String toString() { 
  return DateFormat.getDateTimeInstance().format(new Date(delayTime)); 
} 
}
}

程序运行結果:

开始时间:2019-6-13 20:40:38 2019-6-13 20:40:39 2019-6-13 20:40:41 2019-6-13 20:40:43 完毕時间:2019-6-13 20:40:43

非阻塞队列

ConcurrentLinkedQueue 是一个根据连接连接点的无边线程安全序列,它选用先进先出法的标准对连接点开展排列,在我们加上一个原素的情况下,它会加上到序列的尾端;在我们获得一个因素时,它会回到序列头顶部的原素。它的入队和出队实际操作均运用 CAS(Compare And Set)升级,那样容许好几个进程高并发实行,而且并不会由于上锁而堵塞进程,促使高并发特性更强。ConcurrentLinkedQueue 应用实例:

ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue();
concurrentLinkedQueue.add(\"Dog\");
concurrentLinkedQueue.add(\"Cat\");
while (!concurrentLinkedQueue.isEmpty()) { 
  System.out.println(concurrentLinkedQueue.poll());
}

实行結果:

Dog

Cat

可以看得出无论是阻塞队列还是是非非阻塞队列,操作方法全是相近的,差别是最底层的建立方法。

优先级队列

PriorityQueue 一个根据优先堆的无边优先级队列。优先级队列的原素依照其当然次序开展排列,或是依据结构序列时给予的 Comparator 开展排列,实际在于所采用的构造函数。优先级队列不允许应用 null 原素。PriorityQueue 编码应用实例

Queue<Integer> priorityQueue = new PriorityQueue(new Comparator<Integer>() {  
                                                 @Override    
                                                 public int compare(Integer o1, Integer o2) {
  // 非自然排列,数据倒序        return o2 - o1;    }});priorityQueue.add(3);priorityQueue.add(1);priorityQueue.add(2);while (!priorityQueue.isEmpty()) {    Integer i = priorityQueue.poll();    System.out.println(i);}

程序运行的結果是:

3

2

1

PriorityQueue 留意的点

  1. PriorityQueue 是是非非线程安全的,在线程同步状况下可应用 PriorityBlockingQueue 类取代;
  2. PriorityQueue 不允许插进 null 原素。

有关面试问题

1.ArrayBlockingQueue 和 LinkedBlockingQueue 的差异是啥?

答:ArrayBlockingQueue 和 LinkedBlockingQueue 都完成自阻塞队列 BlockingQueue,他们的差异具体反映在下述一些层面:

  • ArrayBlockingQueue 应用时务必特定容积值,LinkedBlockingQueue 可以无需特定;
  • ArrayBlockingQueue 的最高容积值是应用时特定的,而且特定以后就不允许改动;而 LinkedBlockingQueue 较大的容积为 Integer.MAX_VALUE;
  • ArrayBlockingQueue 数据储存器皿是选用二维数组储存的;而 LinkedBlockingQueue 选用的是 Node 连接点存放的。

2.LinkedList 中 add() 和 offer() 有什么关系?

答:add() 和 offer() 全是加上原素到序列尾端。offer 方式是根据 add 方式完成的,Offer 的源代码如下所示:

public boolean offer(E e) {    return add(e);}

3.Queue 和 Deque 有什么不同?

答:Queue 归属于一般序列,Deque 归属于双端队列。一般序列是先进先出法,也就是仅有优秀的才可以先出;而双端队列则是两边都能插进和删掉原素。

4.LinkedList 归属于一般序列或是双端队列?

答:LinkedList 完成了 Deque 归属于双端队列,因而有着 addFirst(E)、addLast(E)、getFirst()、getLast() 等方式。

5.下列表述不正确的是?

A:DelayQueue 内部结构是根据 PriorityQueue 完成的 B:PriorityBlockingQueue 并不是先进先出法的数据存储方式 C:LinkedBlockingQueue 容积是无穷大的 D:ArrayBlockingQueue 内部结构的数据存储器是二维数组,复位时务必特定序列容积 答:C 题型分析:LinkedBlockingQueue 默认设置容积是 Integer.MAX_VALUE,并并不是无穷大的,源代码如下图所示:

如何手撸一个Java队列?队列详解和面试题汇总(含答案)

6.有关 ArrayBlockingQueue 观点不正确的是?

A:ArrayBlockingQueue 是线程安全的 B:ArrayBlockingQueue 原素容许为 null C:ArrayBlockingQueue 关键应用领域是“经营者-顾客”实体模型 D:ArrayBlockingQueue 务必表明地设定容积 答:B 题型分析:ArrayBlockingQueue 不允许原素为 null,假如加上一个 null 原素,会抛 NullPointerException 出现异常。

7.下列程序运行的结论是啥?

PriorityQueue priorityQueue = new PriorityQueue();priorityQueue.add(null);
System.out.println(priorityQueue.size());

答:程序运行出错,PriorityQueue 不可以插进 null。

8.Java 中多见的阻塞队列有什么?

答:Java 中多见的阻塞队列如下所示:

  • ArrayBlockingQueue,由二维数组构造构成的有限阻塞队列;
  • PriorityBlockingQueue,适用优先级排序的无边阻塞队列;
  • SynchronousQueue,是一个不储存原素的阻塞队列,会立即将每日任务交到顾客,务必等序列中的增加原素被交易后能够再次加上新的原素;
  • LinkedBlockingQueue,由单链表构造构成的阻塞队列;
  • DelayQueue,适用延迟获得要素的无边阻塞队列。

9.有限序列和无边序列有什么差别?

答:有限序列和无边序列的差别如下所示:

  • 有限序列:有固定不动尺寸的序列称为有限序列,例如:new ArrayBlockingQueue(6),6 便是序列的尺寸。
  • 无边序列:指的是沒有设定固定不动尺寸的序列,这种序列的特性是可以立即入役,直到外溢。他们并没有确实无边,他们最高值通常为 Integer.MAXVALUE,仅仅平时非常少能使用这么大的容积(超出 Integer.MAXVALUE),因而从用户的感受上,就等同于 “无边”。

10.怎样手动式完成一个延迟时间线程池?

答:说到延迟时间线程池,大家应当可以第一时间想起要应用 DelayQueue 延迟时间序列来处理这个问题。完成构思,线程池分成经营者和顾客,经营者用以提升信息,顾客用以获得并交易信息,大家只必须经营者把信息放进到 DelayQueue 序列并设定时间延迟,顾客循环系统应用 take() 堵塞获得信息就可以。详细的建立源代码如下所示:

public class CustomDelayQueue {    // 信息序号 
  static AtomicInteger MESSAGENO = new AtomicInteger(1);
public static void main(String[] args) throws InterruptedException { 
  DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();        // 经营者1    
  producer(delayQueue, \"生产者1\");        // 经营者2  
  producer(delayQueue, \"生产者2\");        // 顾客 
  consumer(delayQueue);    }    //生产者    
private static void producer(DelayQueue<DelayedElement> delayQueue, String name) {  
  new Thread(new Runnable() {   
             @Override       
             public void run() {             
    while (true) {                    // 造成 1~5 秒的随机数字           
      long time = 1000L * (new Random().nextInt(5)   1);       
      try {        
        Thread.sleep(time);          
      } catch (InterruptedException e) {      
        e.printStackTrace();          
      }                    // 组成信息体      
      String message = String.format(\"%s,消息序号:%s 推送時间:%s 延迟时间:%s 秒\",                            name, MESSAGENO.getAndIncrement(), DateFormat.getDateTimeInstance().format(new Date()), time / 1000);                    // 生产制造信息   
      delayQueue.put(new DelayedElement(message, time));      
    }   
  }    
}).start();   
}    //顾客   
private static void consumer(DelayQueue<DelayedElement> delayQueue) { 
  new Thread(new Runnable() {     
             @Override  
             public void run() { 
    while (true) {          
      DelayedElement element = null;     
      try {                        // 交易信息           
        element = delayQueue.take();        
        System.out.println(element);            
      } catch (InterruptedException e) {          
        e.printStackTrace();                  
      }           
    }         
  }     
}).start();    } 
// 延迟时间序列目标   
static class DelayedElement implements Delayed {     
  // 到期時间(企业:ms)     
  long time = System.currentTimeMillis();     
// 信息体     
String message;   
// 主要参数:delayTime 时间延迟(企业ms)  
public DelayedElement(String message, long delayTime) {      
  this.time  = delayTime;       
  this.message = message;       
}     
@Override     
// 获得到期時间        public long getDelay(TimeUnit unit) {            return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);        }        @Override        // 序列原素排列        public int compareTo(Delayed o) {            if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS))                return 1;            else if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))                return -1;            else                return 0;        }        @Override        public String toString() {            // 打印消息            return message   \" |实行時间:\"   DateFormat.getDateTimeInstance().format(new Date());        }    }}

以上程序流程适用多生产者,实行的結果如下所示:

生产者1,信息序号:1 推送時间:2019-6-12 20:38:37 延迟时间:2 秒 |实行時间:2019-6-12 20:38:39 生产者2,信息序号:2 推送時间:2019-6-12 20:38:37 延迟时间:2 秒 |实行時间:2019-6-12 20:38:39 生产者1,信息序号:3 推送時间:2019-6-12 20:38:41 延迟时间:4 秒 |实行時间:2019-6-12 20:38:45 生产者1,信息序号:5 推送時间:2019-6-12 20:38:43 延迟时间:2 秒 |实行時间:2019-6-12 20:38:45 ……

汇总

序列(Queue)依照是不是堵塞可分成:阻塞队列 BlockingQueue 和 非阻塞队列。在其中,双端队列 Deque 也是非阻塞队列,双端队列除开有着序列的先进先出法的方式以外,还具有自身特有的方式,如 addFirst()、addLast()、getFirst()、getLast() 等,适用首未插进和删掉原素。序列中较为常见的2个序列也有 PriorityQueue(优先级队列)和 DelayQueue(延迟时间序列),可应用延迟时间序列来完成延迟时间线程池,这也是招聘面试中较为常见的问题之一。必须招聘面试好朋友对延迟时间序列一定要保证心里有数,动手能力写一个线程池也是十分需要的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2022年4月28日 下午1:52
下一篇 2022年4月28日 下午1:54

相关推荐

  • 淘宝刷人气软件哪个好(淘宝流量推广软件排名)

    1、闪佣补单平台 优点:可以选择买号的性别、地区、好评率、购物喜好、消费能力等,降权包赔付,再行业内算是顶尖的平台了,有专业的团队提供全方位服务,可以人工深度浏览,真实收藏加购,独立下单IP,自定义晒图好评,还能免费代发快递。   2、YY平台公会   优点,真实有效;缺点,效率低,价格高,一个要1.5元左右。   3、淘宝威客丶猪八戒威客   优点:真实有效;缺点,效率低,价格高,一个要1.5元…

    2022年5月9日
    740
  • 北京哪里摆地摊最火,北京摆地摊人流量最多的几个地方

    1.宣武区 长椿街国华商场对面有个长椿街西里一条胡同晚上的时候有一些卖小吃的在那里摆地摊白天中午和下午也有摆地摊的 卖什么的都有中午11:30到下午1:30晚上6:00开始一直到深夜虽然在二环里吧不过感觉城管很少在那里蹲点的中午和傍晚的时候没见过有管的2.朝阳区金台路河边9路公交车终点站对面以前经常看见一群卖古董的经常在那里摆地摊顾客主要是一群大叔大妈看的多买的少后来那里好像改造所以现在能不能摆我…

    2022年8月31日
    5.6K0
  • 华为智能手表怎么用(华为智能手表使用说明及测评)

    当你还在为自己手腕上的HUAWEIWATCH的时尚与智能体验所倾倒时,它已经悄然进行了升级,为广大消费者提供通话功能。曾经它可以微信支付、拒接电话等功能已令人惊艳,如今这则利好消息一出,便引发广大消费者的广泛关注。那么,今天小编就为大家解答如何体验HUAWEIWATCH通话功能。 想要HUAWEIWATCH通话,首先需要开蓝牙通话功能,进入“设置”,找到“蓝牙,开启“手表接听电话”,即可使用HUA…

    2022年10月26日
    470
  • 绿色食品加盟怎么样(绿色食品加盟品牌排行榜)

    时间的巨轮不停转动,进入21世纪初,随着经济的推进,国民的消费水平在逐步的提升。同时随着人均收入的提升,广大消费者对食品的追求标准也在水涨船高,消费的观念也从过去的追求“吃饱、穿暖”逐步转变为“吃好、吃出健康”。 那么在食品行业中,过去的老思路和老观念,已经不能跟得上市场的变化,生态、有机、绿色,变成了现在人们消费的主要方向。这也就意味着以农业为主的食品行业,必须做出变革,否则必定被日新月异的市场…

    2022年5月4日
    880
  • 2020音质最好的耳机排名(4款热门降噪耳机对比评测)

    2020年的2月比往年要漫长一点儿,因为是闰月,多了一天。 当我拿到B&OH9三代的时候,终于不再三缺一了。 当今世界四大主流品牌蓝牙降噪旗舰大耳机,总算可以宅在一张八仙桌上,煮酒论名次了。 首先,要排一下座次。按岁数,不对,这四位上下差不了一岁。就按岁月吧,排个出场顺序: 老大:索尼WH1000XM3 老二:BOSE700 老三:森海塞尔大馒头三代 老四:B&OH9…

    2022年9月10日
    690
  • 加盟艺术培训班(少儿美术培训加盟)

    为何要加盟少儿美术?能做到必定水平的加盟品牌在产品上都有分歧的特点,并且在海内当初的市场上都是有必定家长认可度,你不太需求思量若何去抉择产物和谋划治理,假如你是一个生手的话,基本上一年半载的你很难摸清楚每一个产物的关头特点以及将来市场的进展水平。 事实上,很多从事了多年的业内人士并不知道这个行业的未来,所有人都在沿着自己的道路前进,以是你能看到和理解的,就是你要去的那个公司的问题和进度,甚至比现在…

    2022年5月10日
    920
  • win10所有软件都打不开怎么办,win10软件打不开的解决方法

    刚打算打开应用,结果……为什么会打不开啊为什么!下面浦东网络运维工程师培训老师来分析下。 Win10管理员账户Administrator默认关闭和隐藏,就是防止这个高权限账户被“滥用”影响系统安全。不过我们有时候也需要开启该账户,以完成一些特殊任务。但我们在登录Windows10管理员账户后却发现,经常遇到自带应用打不开的现象,甚至有时候开始菜单也打不开,这可如何是好呢? 为您送上三大对策…

    2022年8月6日
    580
  • 英国大学商科排名前十的学校有哪些,英国留学费用汇总

    英国大学商科排名 1UniversityofStAndrews 圣安德鲁斯大学 2UniversityofOxford 牛津大学 3UniversityofBath 巴斯大学 4UniversityCollegeLondon 伦敦大学学院 5LancasterUniversity 兰开斯特大学 611LoughboroughUniversity 拉夫堡大学 6UniversityofWarwick…

    2022年9月3日
    580
  • 职业求职攻略(未来热门行业发展前景及发展趋势)

    又到一年「金三银四」求职季,转眼间三月已结束,你找到好工作登上人生巅峰了吗? 如何抓住仅剩一个月的黄金时间,快速获得最心仪的工作?求职有套路,在摸爬滚打经历了三次求职后,一些心得与君共享。 懒人目录 花最多的时间做职业规划投资有风险,跳槽须谨慎最大限度地寻找求职机会最后的鸡血 花最多的时间做职业规划 对于一直在创业公司高级打杂的我,什么都得干,什么都能干。所以身处职业分叉口,选择自然也多。我是要去…

    2022年10月21日
    280
  • win10鼠标速度怎么调节,win10调节鼠标灵敏度设置教程

    鼠标想必大家都不陌生,它是一种计算机输入设备,形似老鼠而得名,让我们计算机的操作变的更加简单,提高工作效率。当然要想更好的使用鼠标,我们还需要了解一下提高鼠标灵敏度的方法。接下来,我就教大家详细的设置方法 刚刚升级win10系统,想要校准电脑一些设置,调节一下鼠标灵敏度,可是win10系统和其他系统设置方法有些差别,找了很多路径都没有找到调节鼠标灵敏度的方法。下面,我就给大家介绍一下win10系统…

    2022年7月2日
    710

发表回复

登录后才能评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信