掘友等级
获得徽章 0
【Threadlocal】本质是维护Thread对象的threadlocalMap,这样每个线程都是拿到自己线程的map,既然是当前线程的属性那么当然做到了线程分离。Threadlocal只是一个外壳包装,维护为不同线程的threadlocalMap,负责设置值与获取值。
threadlocalMap本质是Entry泛形数组,key-value键值对形式。其中key就是threadlocal本身。
关注:Entry继承weakReference,即下一次gc清理,那么当threadlocal使用完后,由于threadlocal没有强引用引用,会被回收,那么entry的key为空,value也取不出来,发生内存泄露。entry被当前线程的threadlocal map强引用持有,直到线程结束,value才会被清理。
所以最好threadlocal使用后, 手动调用remove
jdk的优化是会下一次操作时先清理key为null的value
【每日一学】同步异步,阻塞非阻塞
通常我们IO都是同步的,即发出调用请求,等待结果返回才继续下一步。
阻塞io,被调用不返回结果,调用者一直等待
非阻塞Io,被调用者马上返回错误或者可以IO的数据,调用者可以马上过去到结果。
同步异步主要针对调用者,调用者不管被调用者的处理情况,直接执行下一步,知道收到被调用者通知。比如Ajax请求,服务器处理完成前浏览器可以做其他事情。
区分同步非阻塞Io和多路复用,
同步非阻塞是调用者自己轮询查看数据是否准备好,而多路复用是委托内核轮询比如select,poll,而epoll则是事件通知形式,内核通知调用者关心的io描述符
【每日一学】jdk7将字符常量池从永久代移至堆中,因为永久代固定大小且不受gc管控,容易造成溢出。jdk8又将永久代去掉,换成元空间直接存放于本地内存,好处是不在堆中,这样系统gc时不必移动这部分空间
interge与int,可以相等,自动拆箱
两个new 创建的interge与integer不能相等,都是指向对象的地址
非new和new创建的integer不能相等
非new创建的两个integer在±127内相等,因为integer. valueof会缓存这个范围的值。
非 new 创建:Integer i=100
servlet2.3中servlet容器filter拦截所有request,包括forward redirect
servlet2.4后默认只拦截外部请求。
spring的onceperrequest保证同个请求同个filter只处理一次,原理是处理过就request. setattributes() ,下次判断有没有这个属性
【每日回顾】
WeakReference:下一次gc的时候清除
softWeekReference:直到内存满的时候清除
PhantomReference:幽灵引用,跟踪对象什么时候清除
【每日回顾】
1.对象头的数据结构不固定
2.无锁001
3.偏向锁101,偏向第一个获得该对象的线程,此时对象头保存线程ID,多次进入只需要确保线程ID是当前线程ID即可。
4.轻量锁00,进入同步代码块时,执行对象的栈中保存对象头,通过CAS更新对象头为指向栈的指针,成功则获得锁,否则膨胀为重量锁
5.重量锁10,
6.自旋锁,即当前对象被其他线程锁定时,不切换线程而而是等待一段时间或者说次数。避免切换线程不必要的cpu资源
第一个线程:偏向—>第二个线程进入如果第一个线程已销毁,则可重偏向—>否则升级为轻量锁
【每日回顾】
1.对象头的数据结构不固定
2.无锁001
3.偏向锁101,偏向第一个获得该对象的线程,不执行同步代码,保持偏向,多次进入不用比较
4.轻量锁00,执行对象的栈中保存对象头,通过CAS更新对象头为指向栈的指针,成功则获得锁,否则膨胀为重量锁
5.重量锁10,
6.自旋锁,即当前对象被其他线程锁定时,不切换线程而而是等待一段时间或者说次数。避免切换线程不必要的cpu资源