操作系统 exce exceptio bool 有一个 fileinput throw 基本数据类型
NIO是new IO,也是非阻塞IO。有Channel、Selector、Buffer、Pipe、FileLock等类。
Buffer在java.nio包
Channel、Selector、Pipe、FileLock等在java.nio.channels包
设置非阻塞configureBlocking(false);
注册选择器register(selector,SelectionKey.OP_XXX)
使用方法read(Buffer) ,write(Buffer)
使用方法open()获取Channel
除了boolean类型没有Buffer类,其他七种基本数据类型都有Buffer缓冲。而byte有两个Buffer缓冲,一个是在堆,一个在文件的内存映射区.
方法clear() 清空Buffer
方法compact()移动Buffer数据到起始位置,设置为position在数据末尾
方法flip() 反转Buffer,将写模式转成读模式
方法rewind() 从0开始读数据
方法hasRemaining()判断是否还有剩余数据
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
MappedByteBuffer 通过
- FileChannel.map方法产生
- Selector selector = Selector.open();
- channel.configureBlocking(false);
- SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
select方法
- int select()
- int select(long timeout)
- int selectNow()
阻塞到至少有一个通道在你注册的事件上就绪了。
- select()
和select()一样,除了最长会阻塞timeout毫秒(参数)。
- select(long timeout)
不会阻塞,不管什么通道就绪都立刻返回
- selectNow()
调用Selector.wakeup()方法,阻塞在select()方法上的线程会立马返回。
用完Selector后调用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效。通道本身并不会关闭。
Selector四种事件用SelectionKey的四个常量来表示:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
在Selector的select方法返回不为0时,获取SelectionKey
- Set < SelectionKey > selectedKeys = selector.selectedKeys();
- Iterator keyIterator = selectedKeys.iterator();
- while (keyIterator.hasNext()) {
- SelectionKey key = keyIterator.next();
- if (key.isAcceptable()) {
- // a connection was accepted by a ServerSocketChannel.
- } else if (key.isConnectable()) {
- // a connection was established with a remote server.
- } else if (key.isReadable()) {
- // a channel is ready for reading
- } else if (key.isWritable()) {
- // a channel is ready for writing
- }
- keyIterator.remove(); //必须移除掉,否则下一次channel还留在selectionkeySet中。
- }
- Pipe pipe = Pipe.open();
- Pipe.SinkChannel sinkChannel = pipe.sink();
- String data = "a sink pipe channel";
- ByteBuffer buf = ByteBuffer.allocate(50);
- buf.clear();
- buf.put(data.getBytes());
- buf.flip();
- while (buf.hasRemaining()) {
- sinkChannel.write(buf);
- }
- Pipe.SourceChannel sourceChannel = pipe.source();
- ByteBuffer buf = ByteBuffer.allocate(50);
- int length = sourceChannel.read(buf);
FileLock与Lock接口相似,但没有实现Lock接口
(1)概念
(2)FileLock FileChannel.lock(long position, long size, boolean shared)
shared的含义:是否使用共享锁,一些不支持共享锁的操作系统,将自动将共享锁改成排它锁。可以通过调用isShared()方法来检测获得的是什么类型的锁。
(3) lock()和tryLock()的区别:
lock()阻塞的方法,锁定范围可以随着文件的增大而增加。无参lock()默认为独占锁;有参lock(0L, Long.MAX_VALUE, true)为共享锁。
tryLock()非阻塞,当未获得锁时,返回null.
(4)FileLock的生命周期:在调用FileLock.release(),或者Channel.close(),或者JVM关闭
(5)FileLock是线程安全的
(6)同一进程内,在文件锁没有被释放之前,不可以再次获取。即在release()方法调用前,只能lock()或者tryLock()一次。
- FileChannel channel = null;
- FileLock lock=null;
- try {
- RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
- channel = raf.getChannel();
- //获得锁方法一:lock(),阻塞的方法,当文件锁不可用时,当前进程会被挂起
- lock = channel.lock();//无参lock()为独占锁
- //lock = channel.lock(0L, Long.MAX_VALUE, true);//有参lock()为共享锁,有写操作会报异常
- //获得锁方法二:trylock(),非阻塞的方法,当文件锁不可用时,tryLock()会得到null值
- //do {
- // lock = channel.tryLock();
- //} while (null == lock);
- } catch (Exception e) {
- }finally{
- if (lock!=null) {
- lock.release();
- }
- if (channel!=null) {
- channel.close();
- }
- }
- package cn.edu.scau.mk;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- /**
- *
- * @author MK
- */
- public class Test {
- volatile static boolean isFinished = false;
- public static void main(String[] args) throws IOException {
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.socket().bind(new InetSocketAddress(888));
- while (!isFinished) {
- SocketChannel socketChannel = serverSocketChannel.accept();
- //1.阻塞模式
- //线程处理socketChannel...
- //2.非阻塞模式
- if (socketChannel != null) {
- //处理socketChannel...
- }
- }
- serverSocketChannel.close();
- }
- }
- package cn.edu.scau.mk;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.SocketChannel;
- /**
- *
- * @author MK
- */
- public class Test {
- volatile static boolean isFinished = false;
- public static void main(String[] args) throws IOException {
- SocketChannel socketChannel = SocketChannel.open();
- socketChannel.configureBlocking(false); //设置为非阻塞
- socketChannel.connect(new InetSocketAddress("https://www.baidu.com", 80));
- String data = "a socket channel connect";
- ByteBuffer buf = ByteBuffer.allocate(48);
- buf.clear();
- buf.put(data.getBytes());
- buf.flip();
- while (!socketChannel.finishConnect()) {
- //等待连接成功或者做其他的事
- }
- //非阻塞状态有可能没有写入数据就返回了
- while (buf.hasRemaining()) {
- socketChannel.write(buf);
- }
- socketChannel.close();
- }
- }
- package cn.edu.scau.mk;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.net.SocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.DatagramChannel;
- import java.nio.channels.SocketChannel;
- /**
- *
- * @author MK
- */
- public class Test {
- volatile static boolean isFinished = false;
- public static void main(String[] args) throws IOException {
- DatagramChannel channel = DatagramChannel.open();
- channel.socket().bind(new InetSocketAddress(888));
- //channel.connect(new InetSocketAddress("www.baidu.com", 80));
- ByteBuffer buf = ByteBuffer.allocate(48);
- buf.clear();
- //接收
- SocketAddress sa = channel.receive(buf);
- //connect通道可以使用read
- //int bytesRead = channel.read(buf);
- buf.clear();
- buf.put("datagram channel".getBytes());
- buf.flip();
- //发送
- int length = channel.send(buf, new InetSocketAddress("www.baidu.com", 80));
- //connect通道可以使用write
- //channel.write(buf);
- channel.close();
- }
- }
Java NIO总结
来源: http://www.bubuko.com/infodetail-2312316.html