未分类知识点记录

  • sel4j是接口,logback,log4j是实现。
    一般来说,我们会用static、final关键字来对日志对象进行修饰。
    设置为private是为了防止其他类使用当前类的日志对象;
    设置为static是为了让每个类中的日志对象只生成一份,日志对象是属于类的,不是属于具体的实例的;
    设置成final是为了避免日志对象在运行时被修改。

  • java序列化一般用于对象变成流进行传输或缓存,一般实现Serializable接口,因为序列化是会判断是否实现了这个接口。
    一般在里面还要有个ID,用来判断序列化是否成功(如果对象升级,用了ID则可以成功序列化回去)。
    一个序列化对象,他的依赖也要是可序列化的,用了transient标识的对象属性不会进行序列化,transient也只能标识对象的非静态属性,序列化也保存的是对象。

  • ConcurrentHashMap
    1.7及以前是使用分段锁,利用Segment内部类管理多个桶,操作里面的数据时进行加锁。put时先定位到对应的Segment数组的值再进行put,这个值也是类似HashMap的结构,put时尝试获取锁,获取不到自旋,在值里散列定位到最终位置操作。
    1.8以后利用CAS和syschronized实现更细粒度的加锁,对每个桶的头节点进行加锁。操作时判断头节点,如果为null则CAS加入节点,如果没扩容且不为空,会进行syschronied加锁。
    get时候都不加锁,因为节点的next指针都是volatile修饰保证可见性,修改立马可见。
    不允许key为null。
    hashtable也是方法上都有syschronized,每次对整个hash表加锁。Collections.syschornizedMap本质上也是全锁。

  • AQS是抽象队列同步器,用来构建锁和同步器的框架。内部基本实现是:一个state状态还有先进先出队列。在资源未空闲会进入队列排队,int类型的状态是为了对共享锁的一个记录,对这个状态的修改也是使用CAS的操作。

  • 泄露和溢出
    对象不再被使用,但是GC又不能进行回收,叫内存泄漏。比如长生命周期对象对短生命周期对象的引用,短生命周期对象不再被使用也回收不了,可以在生命周期结束时置空。
    而内存泄露的增多,又会导致无内存可用造成内存溢出,对象占满堆栈会造成内存溢出。比如方法一直来回调或对象一直来回创建。

  • socket和http
    相同:
    1.都是tcp协议,连接过程基于请求响应模型。
    2.websocket基于http,两者兼容性好。
    不同:
    1.websocket 是长连接,http 是短连接;
    2.websocket 的协议是以 ws/wss 开头,http 对应的是 http/https;
    3.websocket 是有状态的,http 是无状态的;
    4.websocket 连接之后服务器和客户端可以双向发送数据,http 只能是客户端发起一次请求之后,服务器才能返回数据;
    5.websocket 是可以跨域的;
    6.websocket 连接建立之后,数据的传输使用帧来传递,不再需要Request消息。

  • IO
    1.同步阻塞IO。BIO。发起IO系统调用后进程阻塞,直到从内核中拿出数据返回。
    2.同步非阻塞IO。NIO。发起IO系统调用后如果没有数据则返回错误使其不阻塞,并继续发送调用。
    3.多路复用IO。一个或多个线程监视多个文件句柄,遍历找出就绪的文件句柄,通知对应应用程序进行读写。有几种模式:
    select模式,最多可以监视1024个文件描述符。
    poll模式,可以监视无限文件描述符。
    epoll模式,将轮询改为回调,句柄出现就进行回调通知。
    4.信号驱动IO。当进程发起IO操作会在内核注册一个信号处理函数然后返回,等到内核数据就绪发送信号给进程,进程在信号处理函数调用IO返回数据。
    5.异步IO。发起IO操作后返回,内核数据处理好之后通知进程,进程可直接拿到数据。区别是异步IO数据不需要自己从内核中阻塞拷贝。

  • Arraylist扩容
    底层数组,适合改查,1.5倍(除2+原数组长),方式和数组一样,先创建扩容后长数组,再把数据copy过来。

  • 字节流和字符流
    1.字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
    2.字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。
    3.字节流处理单元为1个字节(byte),字符流处理的单元为2个字节的Unicode字符。

  • 类结构初始化顺序
    父类静态属性
    父类静态代码块
    子类静态属性
    子类静态代码块
    父类非静态属性
    父类非静态代码块
    父类构造器
    子类非静态属性
    子类非静态代码块
    子类构造器

  • 查询网站在线人数通过监听session对象的方式来实现在线人数的统计和在线人信息展示,并且让超时的自动销毁。实现继承HttpSessionListener类,监听session的变化来设置在线人数。

  • servlet生命周期:
    1.客户端发起请求,servlet容器解析请求,创建该servlet实例(对应要请求的servlet那个类)。
    2.servlet容器调用servlet的init方法,然后调用servlet的service方法(doGet,doPost啥的)。
    3.servlet容器将响应结果返回给客户端,servlet重新加载或容器重启会调用servlet的destroy方法。
    4.再次请求同一请求,该实例已经存在,就直接调用service方法即可。

  • Redis的过期策略以及内存淘汰机制。
    1.redis采用的是定期删除+惰性删除策略。
    2.定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
    3.于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下。
    4.如果这两方式都没命中,会有内存淘汰机制,配置文件里有。

  • InnoDB 存储引擎的锁的算法有三种:
    Record lock:记录锁,单个行记录上的锁
    Gap lock:间隙锁,锁定一个范围,不包括记录本身
    Next-key lock:record+gap 临键锁,锁定一个范围,包含记录本身

  • 一个普通字符对应两个字节,两个字节为一个最小代码单元。
    一个辅助字符有四个字节,两个代码单元。
    .length()查看的是代码单元数量,一个辅助字符有两个,会乱,使用pointCount码点查看(一个码点代表一个字符,不管是哪种字符),使用chatAt也会得出乱码。

  • JVM定义了线程与主内存之间的抽象关系:共享变量存储在主内存,每个线程都有一个私有的本地内存,本地内存保存了该线程使用到的主内存的副本拷贝,线程对变量的所有操作都必须在本地内存中进行,而不能直接读写主内存的变量。

  • JVM是通过对volatile关键字修饰的对象前后添加屏障实现禁止指令重排序的,在volatile写操作前后加StoreStoreBarrier,在volatile读操作前后加LoadLoadBarrier。变量可见性,被标识不会被拷贝到线程本地内存,直接访问主存,防止脏读。

  • tomcat拥有自定义的类加载器(加载模式是先自己加载,搞不定再给父类,实现方式是重写ClassLoader的findClass和loadClass方法)
    1.实现类的独立加载管理和隔离,防止类冲突(如同名类和不同程序的不同版本包的同一类)
    2.实现热加载,运行时动态更新代码资源(如JSP的编译的.class文件)。检测到文件改变则类加载器对其重新加载,而一般类加载器实现需要重启从而把所有类加载一遍。
    3.安全隔离,防止一个程序内类加载器内存泄漏导致全体内存泄漏。

  • jvm锁的优化
    锁粗化:发现一对象反复加锁,会将锁的力度扩大,覆盖到整个对象以外,就只要上一次整锁了。
    锁消除:确定对象不会出现逃逸即对象作用域或生命周期只在某方法中,会进行,锁消除,即不会有线程安全问题就不上锁。

  • 接口幂等性和防重复提交:幂等性是多个一样的请求情况下保证不重复执行同一状态操作且返回结果相同。放重复提交则是防止多个执行同一状态操作,不保证返回结果相同。
    保证幂等性:
    1.搞个全局唯一业务ID,存起来,操作时判断这个ID存不存在再操作,存在就返回同一返回结果,类似于分布式锁。
    2.数据库搞唯一索引,插入数据时生成唯一索引进行插入,插入失败捕获这个异常返回同一结果。
    3.搞一些状态字段,操作时判断字段状态,正确进行操作且修改状态字段,不正确说明重复则返回同一结果。

  • new ThreadLocal<?>时会把Threadlocal和对应的值放在Thread下的ThreadlocalMap进行存储,ThreadlocalMap一个线程一个,进行线程隔离,则对象的值操作是线程安全的。

  • 内存泄漏的原因是Threadlocal是弱引用,在使用完值后,值V为强引用不会直接进行回收,而Threadlocal为弱引用,一旦GC就会回收。试想K被回收了,V如何才能获取或者删除掉呢,那只能等线程销毁才能把内存回收,那在大部分情况下的线程池呢,就回到了池中不会进行销毁,造成了内存泄漏,一旦这种情况多起来,就会有内存莫名被占用造成内存溢出。即使Threadlocal为强引用,在不进行销毁的情况下,K和V都会有残留,间接造成内存溢出。所以一般来说,在使用完Threadlocal中的值后,将值置空,Threadlocal会慢慢被回收。
    (强软弱虚引用)可以查查看

  • ThreadlcalMap是Thread里的静态内部类,Thread里面的是ThreadLocal.ThreadLocalMap。
    1.ThreadLocalMap里面的Entry继承了WeakReference<ThreadLocal<?>>说明Entry可以持有对象ThreadLocal<?>的弱引用且是对ThreadLocal<?>弱引用的包装类,在Entry加入KV时,K赋值时会调用父类WeakReference的构造方法将K变为弱引用进行持有。
    2.K是继承自WeakReference的父类Reference的成员变量,V是Entry中的成员变量。

  • 一个对象如果只被弱引用引用而没有被其他强引用引用,GC时会被回收。
    设置为static ThreadLocal时,ThreadLocal除了被弱引用指向还会被static标识作为GC root,从而在垃圾回收时不会被回收,保持对值的随拿随用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值