Java知识点(更新)

本文深入探讨了Java中的IO模型、NIO特性及其应用场景,同时解析了序列化的细节及注意事项,并介绍了Java垃圾回收机制的不同方面和技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1  IO ,NIO,NIO2

其实就是几个主要的类:

Buffers :IO没有缓冲,是面向流的。NIO有缓冲,可以提供更加灵活的API。Buffer和Channel一定要配合使用,数据是从buffer写入channel,从channel读入buffer。

Channels :IO没有channel,一个线程管理一个连接,是阻塞式的,连接中当前没有数据,线程阻塞。NIO提供channel,可以让一个线程同时管理多个连接或者读取多个文件,是非阻塞的。注意FileChannel总是阻塞的

Selector :通过selector来选择当前需要处理的channel,如何工作取决于底层操作系统如何实现。比如linux的版本不同,可以支持select poll 或者epoll,epoll是2.6以上才支持,优势是提供回调注册机制,不必轮询整个list来获取需要处理的通道。常用的Nginx就是通过epoll实现高并发连接支持的。

一般连接数较多,而且通信量不密集,可以用NIO比较好。

这里提到容易混淆的两个概念:用户线程请求内核线程读取网络数据。

阻塞 :内核线程在读取过程中,用户线程会询问是否有数据读入内核缓存,如果没有,用户线程会等待,直到下次询问。比如java IO,一个用户线程只能处理一条channel。

非阻塞:等待过程中用户线程去干其他的事情,比如java NIO,询问一个channel没数据,不是阻塞在该channel,而是去处理其他channel,直到下次询问。一个用户线程同时处理多条channel。

同步 :上面两种情况都属于同步,同步还是异步是针对内核线程而言的。用户线程提出请求后,内核线程不会立刻回答,用户线程轮询取得数据。同步的好处就是,用户的请求最终一定会得到响应,或者成功或者失败,只是需要花费cpu轮询,轮询也是一种同步等待。

异步:内核线程立刻响应,失败或者成功。失败,比如无法建立网络连接。成功,表示收到请求,正在处理,有数据到了会通知,不必询问。比如java NIO2。异步通常做法就是callback,或者event的方式。epoll支持。异步的好处显而易见,没有花费无用的cpu时间片在轮询上,不好的地方在于,通知可能不可达。

总之,同步还是异步,描述的是用户与内核的交互关系,一个主动,一个被动。而阻塞非阻塞,描述的是用户的状态。因为同步一般表现为阻塞,所以容易弄混。

当然,NIO还提供许多扩展功能,比如文件属性的操作,随机读写等。


2 序列化

1 Serializable会保存class信息,Externalizable只有类名。效率会好一些,但不会提高明显。

2 static和transit不会序列化。父类没有声明接口,他的字段也不会序列化。

final字段要注意。Serializable反序列化时不会调用构造函数,所以final变量的初始化不要放在构造函数,应该直接初始化,否则当你更新类版本启用新的final变量值的时候,反序列化回来的还是旧的字段值。Externalizable反序列化会调用默认构造函数,如果没有提供,会报错。

4 serialVersionUID要一致才能反序列化,版本控制。如果字段不变,自动生成的ID也不变,说明序列化的是对象信息。ID 由字段决定,如果不指定ID,jvm会自动生成一个,当字段发生改变,反序列化会失败。

5 同一个对象重复序列化两次,即使字段值前后有改变,jvm优化后只会存一个,反序列化出来的两个对象相等,其实还是一个对象,变动的字段值丢失。

6 同一个类new两个对象,连续序列化后,jvm也会优化存储,但是反序列化出来2个不同的对象。

7 单例模式反序列化会生成新的对象,需要改写readResolve方法返回同一个实例。

8序列化方式并不仅仅局限于二进制,也可以基于文本,比如json xml。

9 hadoop有自己的序列化框架实现,storm使用kryo。


3 垃圾收集

1 堆区(新代 老代), 栈区, 方法区(永久代), native区。垃圾收集,指的是堆区的内存回收。堆的特点是动态的灵活分配,缺点是慢。栈的存取速度快,但是大小固定,即需要编译时确定。

2 并行:多个收集线程同时垃圾回收。 并发:收集线程和工作线程同时运行。

新代:minor GC。都是复制算法。分为三块,eden和两个survivor1 2。默认比例811。

a) 回收eden和s1的非存活对象。b) 将存活的copy到s2。c) 重复。 d) 在s1和s2来回多次还存活的进入老代。

Serial串行收集器:client模式启动时的默认新代收集器。单线程。不能并行,不能并发。

ParNew并行收集器:多线程版的串行收集器。CMS的默认搭配。可以并行,不能并发。

Paralle Scavenge:吞吐量优先收集器。可以控制业务线程运行时间与cpu总时间的比值。可以并行,不能并发。

-XX:MaxGCPauseMillis 每次收集的停顿时间,它通过修改新代的大小来达到时间控制。

-XX:GCTimeRatio 手机时间占总时间的比例。

-XX:+UseAdaptiveSizePolicy 自适应调节

4 老代:full GC

Serial Old收集器:client模式启动时的默认老代收集器。单线程。与新代的Serial搭配使用。不能并行,不能并发。标记整理算法。

Parallel Old收集器:与Paralle Scavenge搭配使用。可以并行,不能并发。标记整理算法。

CMS收集器:只能与ParNew搭配使用。追求短的收集停顿时间,提高用户体验。标记清除算法。通过参数配置整理功能,以消除内存碎片。可以并行,可以并发。注意因为并发,收集过程中会不断有用户线程新的无用对象产生,所以不能等老代填满,通过参数设置比例触发full gc。

G1 收集器:jdk7支持。标记整理算法。特点是 内存区域划分, 然后优先级队列,在指定的回收时间内,优先回收垃圾对象多的区域,以达到最好的回收效率。


4 多线程

1 volatile 对象创建在堆中,当线程的某个方法调用使用到该对象的某个成员变量时,会首先在该线程栈里分配一个frame,然后将变量的值在frame里做一份copy,原始类型就是值,引用类型就是句柄。这样无论对象成员变量如何变化,该线程方法调用中始终无法感知,造成不一致的问题。使用volatile ,强制线程每次使用堆内存中的值。volatile并不能代替独占锁,即不能依靠它来实现同步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值