面试题之并发相关专栏三

一、ReentrantLock是如何实现可重入的?

ReentrantLock内部自定义了同步器Sync,其实就是加锁的时候通过CAS算法,将线程对象放到一个双向链表中,每次获取锁的时候,看下当前维护的那个线程ID和当前请求的线程ID是否一样,一样就可重入。

二、请说说CyclicBarrier和CountDownLatch的异同?

  •  CountDownLatch 是不可以重置的,所以无法重复使用,而CyclicBarrier可以重复使用栅栏;
  • CountDownLatch目的是让一个线程等待其他N个线程达到某个条件后,自己再去做某个事情;而CyclicBarrier的目的是让N多个线程互相等待直到所有线程都达到某个状态,这N个线程再继续执行各自后续操作;

三、为什么要用线程池?Java线程池的好处?

  • 重用已经存在的线程,减少了线程的创建和销毁的开销;
  • 可有效控制最大并发的线程数,提高了系统资源的使用率避免很多竞争,避免了OOM、死锁等;
  • 可以提供定时和定期的执行方式,单线程,并发数量的控制等功能;

四、Java中线程池的种类?

  • newFixedThreadPool(int nThreads)      //启动固定线程数的线程池
  • newCachedThreadPool()    //按需分配的线程池
  • newSingleThreadExecutor()    //单个线程的线程池
  • ScheduledThreadPoolExecutor()    //定时,定期执行任务的线程池
  • ThreadPoolExecutor()   //指定线程数的线程池

五、请谈谈ThreadPoolExecutor线程池的几个核心参数?

  • 【1】corePoolSize:线程池中的常驻核心线程的数量(总线程量可大于等于这个值);
  • 【2】maximumPoolSize:线程池中能够容纳同时执行的最大线程数,此值必须大于等于1(总线程量不可能超越这个数值);
  • 【3】keepAliveTime:多余的空闲线程的存活时间。当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁直到只剩下corePoolSize个线程为止;
  • 【4】unit:keepAliveTime的时间单位;
  • 【5】workQueue:任务队列,被提交但尚未被执行的任务;例如: 提交了10个任务,但是线程只有5个,于是另外5个提交但没开始执行的任务就存放到了workQueue工作队列里面,既然是队列,我们知道,实现队列的方式有很多种,比如ArrayBlockQueue、LinkedBlockQueue等等,选择不同的队列就会带来不同的问题;
  1.     ArrayBlockQueue:存在一个任务过多超出队列长度
  2.     LinkedBlockQueue:接受过多的任务可能会占用太多内存,造成内存崩溃;
  • 【6】threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程,一般使用默认的线程工厂即可
  • 【7】handler:拒绝策略,表示当队列满了,并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝请求执行的runnable的策略。默认拒绝策略是AbortPolicy,抛出异常阻止程序
  1.  AbortPolicy:默认的拒绝策略,当提交的任务数量大于线程池中的最大数量时,会抛出RejectedExecutionException,阻止系统正常运行。
  2.     DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常,如果允许任务丢失,这是最好的一种策略(什么也不做,直接忽略).
  3.     DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中,尝试再次提交当前任务(丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置)
  4.     CallerRunsPolicy:“调用者运行”一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量(直接由提交任务者执行这个任务)
发布了250 篇原创文章 · 获赞 112 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/105332063