Java基础
2020-11-04 14:51:05 0 举报
AI智能生成
Java基础总结
作者其他创作
大纲/内容
hashCode和equals
equals 和 == 的区别
hashCode在HashMap,HashSet之中的用处
方法重载和重写
方法重载的优先级
内部类和静态内部类
实例化顺序
char能否存一个中文字符
多继承的解决方式
内部类
多interface
io
文件IO
流
按格式划分
字节流
字符流
按传输方向划分
输入流
输出流
常用的流
文件字节流
FileInputStream
FileOutputStream
FileOutputStream
文件字符流
FileReader
FileWriter
动态字节数组流
ByteArrayInputStream
ByteArrayOutputStream
装饰者字节流
DataOutputStream
DataInputStream
缓存流
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
BufferedOutputStream
BufferedReader
BufferedWriter
nio中的FileChannel
IO模型,从操作系统角度出发
阻塞IO模型
文件
隔壁的流都是阻塞io模型
网络
socket
非阻塞 IO 模型
现实情况很少见这种使用案例
多路复用 IO 模型
select/poll
信号驱动 IO 模型
select/epoll
异步 IO 模型
linux之中没有实现,
windows之中有实现
windows之中有实现
AsynchronousFileChannel
java7中的aio只是一个伪实现
Java体系中IO
oio/io
阻塞模型
FileInputStream/FileOuptStream
FileWriter/FileRead
nio
使用的是select/poll
三个核心部件
Channel
FileChannel
文件IO
Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。
FileChannel的使用步骤
打开FileChannel
FileChannel.open()
FileInputStream/FileOutputStream.getChannel()
RandomAccessFIle.getChannel()
声明buffer
ByteBuffer buf = ByteBuffer.allocate(48);
读写数据
读数据
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
int bytesRead = inChannel.read(buf);
写数据
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
关闭FileChannel
channel.close();
零拷贝
mmap
transferTo
transferFrom
DatagramChannel
UDP协议
使用
SocketChannel
TCP协议
使用5大步骤
打开 SocketChannel
SocketChannel socketChannel = SocketChannel.open();
选择阻塞模式/非阻塞模式
默认阻塞模式
非阻塞模式
socketChannel.configureBlocking(false);
创建连接
读写数据
读
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
int bytesRead = socketChannel.read(buf);
写
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
关闭 SocketChannel
socketChannel.close();
ServerSocketChannel
TCP协议
使用5大步骤
打开 ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
选择阻塞模式/非阻塞模式
默认阻塞模式
非阻塞模式
serverSocketChannel .configureBlocking(false);
监听新进来的连接
处理新连接
关闭 ServerSocketChannel
serverSocketChannel.close();
Selector
Selector能够处理多个通道
Selector使用一般有4个步骤
创建一个Selector
Selector selector = Selector.open();
向Selector注册通道
channel.configureBlocking(false); //与Selector一起使用时,Channel必须处于非阻塞模式下
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
register()方法的第二个参数
Connect
SelectionKey.OP_CONNECT
Accept
SelectionKey.OP_ACCEPT
Read
SelectionKey.OP_READ
Write
SelectionKey.OP_WRITE
如果你对不止一种事件感兴趣,那么可以用“位或”操作符将常量连接起来
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
register() 返回值:SelectionKey
SelectionKey 有如下属性
interest集合
interest集合是你所选择的感兴趣的事件集合。
ready集合
ready 集合是通道已经准备就绪的操作的集合。
Channel
这个就是之前注册那个Channel,只是为了访问方便
Selector
这个就是注册的selector,这样设计只是为了访问方便
附加的对象(可选)
可以将一个对象或者更多信息附着到SelectionKey上,这样就能方便的识别某个给定的通道。
选择通道 selector.select()
select()方法
int select()
阻塞到至少有一个通道在你注册的事件上就绪了。
int select(long timeout)
select(long timeout)和select()一样,除了最长会阻塞timeout毫秒(参数)。
int selectNow()
不会阻塞,不管什么通道就绪都立刻返回
对感兴趣的事件做出回应 selectedKeys()
Set<SelectionKey> selectedKeys = selector.selectedKeys();
一般有两种处理方式
1. 使用第二步的注册通道的时候的SelectedKey代表的通道,判断是否是这个通道做对应通道感兴趣的事情
2. 遍历所有感兴趣的事情,做出回应
两个特殊的方法
wakeUp()
close()
Buffer
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
Buffer的capacity,position和limit
capacity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
position
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1。
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
Buffer读写数据一般遵循以下四个步骤
1. 写入数据到Buffer
从Channel写到Buffer的例子
int bytesRead = inChannel.read(buf); //read into buffer.
通过put方法写Buffer的例子
buf.put(127);
2. 调用flip()方法
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。
3. 从Buffer中读取数据
从Buffer中读取数据有两种方式
从Buffer读取数据到Channel。
int bytesWritten = inChannel.write(buf);
使用get()方法从Buffer中读取数据。
byte aByte = buf.get();
重读
rewind()
Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)。
4. 调用clear()方法或者compact()方法
clear()方法会清空整个缓冲区。
compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
基本用法
MappedByteBuffer
这是一种特殊的buffer
Channel vs Buffer vs Selector
Channel vs Buffer
Channel 是双向的
既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
通道可以异步地读写。
Channel中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
Scatter/Gather
scatter
代码实例
gather
代码实例
Pipe
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
Pipe原理的图
使用
创建管道
Pipe pipe = Pipe.open();
向管道写数据
Pipe.SinkChannel sinkChannel = pipe.sink(); //要向管道写数据,需要访问sink通道。
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
sinkChannel.write(buf);
}
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
sinkChannel.write(buf);
}
从管道读取数据
Pipe.SourceChannel sourceChannel = pipe.source(); //从读取管道的数据,需要访问source通道
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = sourceChannel.read(buf); //read()方法返回的int值会告诉我们多少字节被读进了缓冲区。
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = sourceChannel.read(buf); //read()方法返回的int值会告诉我们多少字节被读进了缓冲区。
Path
Java NIO 2 中的一个定位资源的工具类
Files
Java NIO 2 中的一个文件操作类
Files.exists()
Files.createDirectory()
Files.copy()
Files.move()
Files.delete()
Files.walkFileTree()
Files.createDirectory()
Files.copy()
Files.move()
Files.delete()
Files.walkFileTree()
io vs nio
面向流与面向缓冲
Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。
阻塞与非阻塞IO
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。
io 效率不一定比nio慢,Files.copy() 使用的就是io的文件流,但是效率比nio还快,nio的优势在于高并发。
io需要阻塞。
io需要阻塞。
Reactor模式
C10K问题
单线程单Reactor模型
多线程单Reactor模型
多线程多Reactor模型
面向对象/面向过程
面向对象的特征
instanceof vs isAssignableForm
什么是隐式转换,什么式显式转换
什么是装箱,什么是拆箱
error 和 exception
String vs StringBuilder vs StringBuffer
字符串常量池
什么是注解
0 条评论
下一页