首页 课程 师资 教程 报名

都在收藏的Java程序员常见面试题库

  • 2020-01-18 15:11:59
  • 2434次 动力节点


都在收藏的Java程序员常见面试题库


  1. synchronized和reentrantlock异同


  相同点


  都实现了多线程同步和内存可见性语义


  都是可重入锁


  不同点


  实现机制不同 synchronized通过java对象头锁标记和Monitor对象实现 reentrantlock通过CAS、ASQ(AbstractQueuedSynchronizer)和locksupport(用于阻塞和解除阻塞)实现 synchronized依赖jvm内存模型保证包含共享变量的多线程内存可见性 reentrantlock通过ASQ的volatile state保证包含共享变量的多线程内存可见性


  使用方式不同 synchronized可以修饰实例方法(锁住实例对象)、静态方法(锁住类对象)、代码块(显示指定锁对象) reentrantlock显示调用trylock()/lock()方法,需要在finally块中释放锁


  功能丰富程度不同 reentrantlock提供有限时间等候锁(设置过期时间)、可中断锁(lockInterruptibly)、condition(提供await、signal等方法)等丰富语义 reentrantlock提供公平锁和非公平锁实现 synchronized不可设置等待时间、不可被中断(interrupted)


  2. concurrenthashmap为何读不用加锁


  jdk1.7


  1)HashEntry中的key、hash、next 均为final 型,只能表头插入、删除结点


  2)HashEntry类的value域被声明为volatile型


  3)不允许用null作为键和值,当读线程读到某个HashEntry的 value域的值为null时,便知道产生了冲突——发生了重排序现象(put设置新value对象的字节码指令重排序),需要加锁后重新读入这个value值


  4)volatile变量count协调读写线程之间的内存可见性,写操作后修改count,读操作先读count,根据happen-before传递性原则写操作的修改读操作能够看到


  jdk1.8


  1)Node的val和next均为volatile型


  2)tabAt和casTabAt对应的unsafe操作实现了volatile语义


  3. ContextClassLoader(线程上下文类加载器)的作用


  越过类加载器的双亲委派机制去加载类,如serviceloader实现


  使用线程上下文类加载器加载类,要注意保证多个需要通信的线程间的类加载器应该是同一个,防止因为不同的类加载器导致类型转换异常(ClassCastException)


  4. tomcat 类加载机制


都在收藏的Java程序员常见面试题库


  不同应用使用不同的 webapp类加载器,实现应用隔离的效果,webapp类加载器下面是jsp类加载器


  不同应用共享的jar包可以放到Shared类加载器/shared目录下


  5. osgi类加载机制


都在收藏的Java程序员常见面试题库


  osgi类加载模型是网状的,可以在模块(Bundle)间互相委托


  osgi实现模块化热部署的关键是自定义类加载器机制的实现,每个Bundle都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换


  当收到类加载请求时,osgi将按照下面的顺序进行类搜索:


  1)将以java.*开头的类委派给父类加载器加载


  2)否则,将委派列表名单(配置文件org.osgi.framework.bootdelegation中定义)内的类委派给父类加载器加载


  3)否则,检查是否在Import-Package中声明,如果是,则委派给Export这个类的Bundle的类加载器加载


  4)否则,检查是否在Require-Bundle中声明,如果是,则将类加载请求委托给required bundle的类加载器


  5)否则,查找当前Bundle的ClassPath,使用自己的类加载器加载


  6)否则,查找类是否在自己的Fragment Bundle中,如果在,则委派给Fragment Bundle的类加载器加载


  7)否则,查找Dynamic Import-Package(Dynamic Import只有在真正用到此Package的时候才进行加载)的Bundle,委派给对应Bundle的类加载器加载


  8)否则,类查找失败


  6. 如何结束一个一直运行的线程


  使用退出标志,这个flag变量要多线程可见


  使用interrupt,结合isInterrupted()使用


  7. threadlocal使用场景及问题


  threadlocal并不能解决多线程共享变量的问题,同一个 threadlocal所包含的对象,在不同的thread中有不同的副本,互不干扰


  用于存放线程上下文变量,方便同一线程对变量的前后多次读取,如事务、数据库connection连接,在web编程中使用的更多


  问题: 注意线程池场景使用threadlocal,因为实际变量值存放在了thread的threadlocalmap类型变量中,如果该值没有remove,也没有先set的话,可能会得到以前的旧值


  问题: 注意线程池场景下的内存泄露,虽然threadlocal的get/set会清除key(key为threadlocal的弱引用,value是强引用,导致value不释放)为null的entry,但是最好remove


  8. 线程池从启动到工作的流程


  刚创建时,里面没有线程


  调用 execute() 添加任务时:


  1)如果正在运行的线程数量小于核心参数corePoolSize,继续创建线程运行这个任务


  2)否则,如果正在运行的线程数量大于或等于corePoolSize,将任务加入到阻塞队列中


  3)否则,如果队列已满,同时正在运行的线程数量小于核心参数maximumPoolSize,继续创建线程运行这个任务


  4)否则,如果队列已满,同时正在运行的线程数量大于或等于 maximumPoolSize,根据设置的拒绝策略处理


  5)完成一个任务,继续取下一个任务处理


  6)没有任务继续处理,线程被中断或者线程池被关闭时,线程退出执行,如果线程池被关闭,线程结束


  7)否则,判断线程池正在运行的线程数量是否大于核心线程数,如果是,线程结束,否则线程阻塞。因此线程池任务全部执行完成后,继续留存的线程池大小为corePoolSize


  9. 阻塞队列BlockingQueue take和poll区别


  poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null


  take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻塞直到BlockingQueue有新的对象被加入


  10. 如何从FutureTask不阻塞获取结果


  get(long timeout,TimeUnit unit),超时则返回


  轮询,先通过isDone()判断是否结束,然后调用get()


都在收藏的Java程序员常见面试题库


      以上就是动力节点Java培训机构小编介绍的“都在收藏的Java程序员常见面试题库”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。


相关推荐


最新最全java面试题及答案(初级到高级)


史上最全的中高级JAVA工程师面试题及答案汇总


Java高级开发工程师面试题


2019史上最全java面试题题库大全800题


哪有资深java工程师面试题


选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交