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
}
}
}