分布式服务框架之NIO(一)
??? NIO在实现分布式服务框架中非阻塞高并发的服务器端功能十分有用。抽空学了下,下面的学习过程中接触到的代码示例,这些代码基本演示了NIO的最基本的一些特性。
??
??? (一)Buffer:
???? 代码一:演示直接缓冲区的使用
??
import java.nio.ByteBuffer;public class ByteBufferDemo01 { public static void main(String[] args) { //直接缓冲区 ByteBuffer buf = ByteBuffer.allocateDirect(10); byte temp[] = { 1, 2, 3 }; buf.put(temp); buf.flip(); System.out.print("主缓冲区中的内容:"); while (buf.hasRemaining()) { int x = buf.get(); System.out.print(x + "、"); } }}
?
??? 代码二:演示缓冲区的基本使用
???
import java.nio.IntBuffer;public class IntBufferDemo01 { public static void main(String[] args) { // 准备出10个大小的缓冲区 IntBuffer buf = IntBuffer.allocate(10); System.out.print("1、写入数据之前的position、limit和capacity:"); System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()); int temp[] = { 1, 2, 3 }; buf.put(5); buf.put(temp); System.out.print("2、写入数据之后的position、limit和capacity:"); System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()); System.out.println(); //重设缓冲区 buf.flip(); System.out.print("3、准备输出数据时的position、limit和capacity:"); System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " + buf.capacity()); System.out.print("缓冲区中的内容:"); while (buf.hasRemaining()) { int x = buf.get(); System.out.print(x + "、"); } }}
?
?? 代码三:子缓冲区的使用
??
import java.nio.IntBuffer;public class IntBufferDemo02 { public static void main(String[] args) { //创建缓冲区,并初始化 IntBuffer buf = IntBuffer.allocate(10); IntBuffer sub = null; for (int i = 0; i < 10; i++) { buf.put(i * 2 + 1); } //需要通过slice() 创建子缓冲区,可通过子缓冲区修改主缓冲区内容 buf.position(2); buf.limit(6); sub = buf.slice(); for (int i = 0; i < sub.capacity(); i++) { int temp = sub.get(i); sub.put(temp - 1); } //重设缓冲区 buf.flip(); buf.limit(buf.capacity()); System.out.print("主缓冲区中的内容:"); while (buf.hasRemaining()) { int x = buf.get(); System.out.print(x + " 、"); } }}
?
?? 代码四:只读缓冲区
??
import java.nio.IntBuffer;public class IntBufferDemo03 { public static void main(String[] args) { //准备出10个大小的缓冲区,并初始化 IntBuffer buf = IntBuffer.allocate(10); IntBuffer read = null; for (int i = 0; i < 10; i++) { buf.put(2 * i + 1); } // 创建只读缓冲区 read = buf.asReadOnlyBuffer(); // 重设缓冲区 read.flip(); System.out.print("主缓冲区中的内容:"); while (read.hasRemaining()) { int x = read.get(); System.out.print(x + "、"); } //修改,错误 // read.put(30) ; }}
?
?
?
?
?
?? (二)Channel
?
?? 代码一:通道写入文件
???
import java.io.File;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class FileChannelDemo01 { public static void main(String[] args) throws Throwable { //初始化 String infos[] = { "test1", "test2", "test3" }; FileOutputStream output = new FileOutputStream("D:" + File.separator + "out.txt"); //读取 FileChannel fout = output.getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024); for (String info : infos) { buf.put(info.getBytes()); } //重设缓冲区(非常重要) buf.flip(); //写入 fout.write(buf); fout.close(); output.close(); }}
?
? 代码二:通道的双向性,可读和可写
?
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class FileChannelDemo02 { /** * 通道是双向的,可读,可写 * * @param args * @throws Throwable */ public static void main(String[] args) throws Throwable { File file1 = new File("d:" + File.separator + "out.txt"); File file2 = new File("d:" + File.separator + "in.txt"); FileInputStream input = null; FileOutputStream output = null; output = new FileOutputStream(file2); input = new FileInputStream(file1); FileChannel fout = output.getChannel(); FileChannel fin = input.getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024); while ((fin.read(buf)) != -1) { buf.flip(); fout.write(buf); buf.clear(); } fin.close(); fout.close(); output.close(); }}
?
? 代码三:MappedByteBuffer的使用
??
import java.io.File;import java.io.FileInputStream;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;public class FileChannelDemo03 { public static void main(String[] args) throws Throwable { File file = new File("d:" + File.separator + "mldn.txt"); FileInputStream input = null; input = new FileInputStream(file); FileChannel fin = null; // 定义输入的通道 fin = input.getChannel(); // 得到输入的通道 MappedByteBuffer mbb = null; mbb = fin.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); byte data[] = new byte[(int) file.length()]; // 开辟空间接收内容 int foot = 0; while (mbb.hasRemaining()) { data[foot++] = mbb.get(); // 读取数据 } System.out.println(new String(data)); // 输出内容 fin.close(); input.close(); }}
??
?
???
?? (三)Charset
??? 代码一:编码和解码
???
import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.nio.charset.CharsetEncoder;public class CharsetEnDeDemo { /** * 编码和解码操作 * @param args */ public static void main(String[] args) throws Throwable{ Charset utf=Charset.forName("UTF-8"); //得到编码器和解码器 CharsetEncoder encoder=utf.newEncoder(); CharsetDecoder decoder=utf.newDecoder(); CharBuffer cb=CharBuffer.wrap("NIO可以用来构建高性能服务器"); //编码和解码 ByteBuffer buf=encoder.encode(cb); System.out.println(decoder.decode(buf)); }
?
? 代码二:获取全部可用的字符集
?
import java.nio.charset.Charset;import java.util.Map;import java.util.SortedMap;public class GetAllCharsetDemo { public static void main(String[] args) { //得到全部可用的字符集 SortedMap<String, Charset> all = Charset.availableCharsets(); for (Map.Entry<String, Charset> entry : all.entrySet()) { System.out.println(entry.getKey() + " --->" + entry.getValue()); } }}
?
??
?? (四)FileLock
??? 代码一:文件独占锁的使用
????
import java.io.File;import java.io.FileOutputStream;import java.nio.channels.FileChannel;import java.nio.channels.FileLock;public class FileLockDemo { public static void main(String[] args) throws Throwable { File file = new File("d:" + File.separator + "out.txt"); FileOutputStream output = null; output = new FileOutputStream(file, true); FileChannel fout = output.getChannel(); FileLock lock = fout.tryLock(); if (lock != null) { System.out.println(file.getName() + "文件锁定30秒"); Thread.sleep(30000); lock.release(); System.out.println(file.getName() + "文件解除锁定"); } fout.close(); output.close(); }}
?
??
???(五)selector
????代码一:无阻塞服务端代码示例
???
import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.Date;import java.util.Iterator;import java.util.Set;public class DataServer { /** * * @param args */ public static void main(String[] args) throws Throwable { int ports[] = { 8000, 8001, 8002, 8003, 8005, 8006 }; // 表示五个监听端口 Selector selector = Selector.open(); // 通过open()方法找到Selector for (int i = 0; i < ports.length; i++) { ServerSocketChannel initSer = null; initSer = ServerSocketChannel.open(); // 打开服务器的通道 initSer.configureBlocking(false); // 服务器配置为非阻塞 ServerSocket initSock = initSer.socket(); InetSocketAddress address = null; address = new InetSocketAddress(ports[i]); // 实例化绑定地址 initSock.bind(address); // 进行服务的绑定 initSer.register(selector, SelectionKey.OP_ACCEPT); // 等待连接 System.out.println("服务器运行,在" + ports[i] + "端口监听"); } // 要接收全部生成的key,并通过连接进行判断是否获取客户端的输出 int keysAdd = 0; while ((keysAdd = selector.select()) > 0) { // 选择一组键,并且相应的通道已经准备就绪 Set<SelectionKey> selectedKeys = selector.selectedKeys();// 取出全部生成的key Iterator<SelectionKey> iter = selectedKeys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); // 取出每一个key if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); // 接收新连接 client.configureBlocking(false);// 配置为非阻塞 ByteBuffer outBuf = ByteBuffer.allocateDirect(1024); // outBuf.put(("当前的时间为:" + new Date()).getBytes()); // 向缓冲区中设置内容 outBuf.flip(); client.write(outBuf); // 输出内容 client.close(); // 关闭 } } selectedKeys.clear(); // 清楚全部的key } }}
?
?