当前位置:网站首页 > 编程语言 > 正文

阻塞队列的作用(阻塞队列的使用场景)



  1.synchronized和reentrantlock异同

  相同点

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

  都是可重入锁

  不同点

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

  使用方式不同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类加载机制

image.png

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

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

  5.osgi类加载机制

image.png

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

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

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

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

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

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

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

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

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

  7)否则,查找DynamicImport-Package(DynamicImport只有在真正用到此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.阻塞队列BlockingQueuetake和poll区别

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

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

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

  get(longtimeout,TimeUnitunit),超时则返回

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

  11.blockingqueue如果存放了比较关键的数据,系统宕机该如何处理

  开放性问题,欢迎讨论

  将队列持久化,比较麻烦,需要将生产数据持久化到磁盘,持久化成功才返回,消费者线程从磁盘加载数据到内存阻塞队列中,维护消费offset,启动时,根据消费offset从磁盘加载数据

  加入消息队列,保证消息不丢失,生成序列号,消费幂等,根据消费进程决定系统重启后的生产状态

  12.NIO与传统I/O的区别

  节约线程,NIO由原来的每个线程都需要阻塞读写变成了由单线程(即Selector)负责处理多个channel注册(register)的兴趣事件(SelectionKey)集合(底层借助操作系统提供的epoll()),nettybossgroup处理accept连接(没看明白为什么bossgroup设置多个thread的必要性),workergroup处理具体业务流程和数据读写

  NIO提供非阻塞操作

  传统I/O以流的方式处理数据,而NIO以块的方式处理数据,NIO提供bytebuffer,分为堆内和堆外缓冲区,读写时均先放到该缓冲区中,然后由内核通过channel传输到对端,堆外缓冲区不走内核,提升了性能

  13.list中存放可重复字符串,如何删除某个字符串

  调用iterator相关方法删除

  倒删,防止正序删除导致的数组重排,index跳过数组元素问题

  14.有哪些GCROOTS(跟日常开发比较相关的是和此相关的内存泄露)

  所有Java线程当前活跃的栈帧里指向GC堆里的对象的引用,因此用不到的对象及时置null,提升内存回收效率

  静态变量引用的对象,因此减少静态变量特别是静态集合变量的大小,集合存放的对象覆写euqls()和hashcode(),防止持续增长

  本地方法JNI引用的对象

  方法区中的常量引用的对象,因此减少在长字符串上调用String.intern()

  classloader加载的class对象,因此自定义classloader无效时及时置null并且注意类加载器加载对象之间的隔离

  jvm里的一些静态数据结构里指向GC堆里的对象的引用

  以上就是动力节点java培训机构小编介绍的“电信Java面试:常见的14个Java面试题”的内容,希望对大家有帮助,更多java最新资讯请继续关注动力节点java培训机构官网,每天会有精彩内容分享与你。

到此这篇阻塞队列的作用(阻塞队列的使用场景)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 网址访问拦截怎么设置(网址访问限制怎么设置)2026-03-29 15:45:10
  • 蓝牙断开连接后怎么重新连接(蓝牙断开连接后怎么重新连接手机)2026-03-29 15:45:10
  • 游戏的分类有哪些类型(游戏有哪几种分类)2026-03-29 15:45:10
  • 网页传输文字(网页传送文字)2026-03-29 15:45:10
  • 中国阶级分层图小康(中国阶级分明)2026-03-29 15:45:10
  • ssh免密码登录配置(ssh免密码登录配置linux)2026-03-29 15:45:10
  • jvm内存模型图(介绍jvm内存模型)2026-03-29 15:45:10
  • mt19937(mt19937原理)2026-03-29 15:45:10
  • 对乙酰氨基酚片联合用药(对乙酰氨基酚片可以连着吃吗)2026-03-29 15:45:10
  • 柯美c7000控制器连不上(柯美c7000控制器连不上网)2026-03-29 15:45:10
  • 全屏图片