NIO通道,Pipe管道

NIO_NIO与IO区别

传统的IO:单向的

NIO模型:双向的

NIO_缓冲区(Buffer)的数据存取

package com.nio;

import java.nio.ByteBuffer;

public class NioSample {
	public static void main(String[] args) {
		String str="测试数据";
		ByteBuffer buffer=ByteBuffer.allocate(10);//开辟缓存空间
		System.out.println("位置指针"+buffer.position()+"容量指针"+buffer.capacity()+"分割指针"+buffer.limit());
		buffer.put(str.getBytes());
		System.out.println("存过数据后--位置指针"+buffer.position()+"容量指针"+buffer.capacity()+"分割指针"+buffer.limit());
		buffer.flip();//重置指针
		System.out.println("重置filp后--位置指针"+buffer.position()+"容量指针"+buffer.capacity()+"分割指针"+buffer.limit());
		byte[] b=new byte[buffer.limit()];
		while(buffer.hasRemaining()) {
			buffer.get(b);
			System.out.println(new String(b));
		}
		buffer.clear();//清空缓存buffer
	}
}

NIO_直接缓冲区与非直接缓冲区

NIO_通道(Channel)的原理与获取

package com.nio;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NIOchannel {
	public static void main(String[] args) throws IOException {
		//读取本地文件到控制台。使用通道 channel 
		//管道类似于火车轨道。但是还需要火车 buffer
		//流是单向的。管道是双向的。能读能写
		//创建输入字节流路径
		FileInputStream fis=new FileInputStream("a.txt");
		//建立通道
		FileChannel  channel=fis.getChannel();//通道是建立在字节流之上
		//开辟缓存空间  火车
		ByteBuffer buffer=ByteBuffer.allocate(20);//开辟缓存空间 并且分配大小
		ByteArrayOutputStream bos=new ByteArrayOutputStream();//输出流
		int data=0;
		//使用通道channel读缓存buffer的内容
		while((data=channel.read(buffer))!=-1) {
			buffer.flip();//刷新指针
			while(buffer.hasRemaining()) {//判断缓存是否有数据
				bos.write(buffer.get());//缓存 一个字节一个字节向外拿。存储到输出流中
			}
			buffer.clear();//清空缓存
		}
		//读取到的内容
		System.out.println(new String(bos.toByteArray()));
		channel.close();
	}
}

NIO_通道的数据传输与内存映射文件

public class TestChannel {
    //1.利用通道来完成文件的复制
    @Test
    public void test1() {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            fis = new FileInputStream("1.jpg");
            fos = new FileOutputStream("3.jpg");
            //2.获取通道
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();
            //3.分配一个指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);

            //4.将通道中的数据存入缓冲区中读取数据
            while (inChannel.read(buf) != -1) {
                buf.flip();//切换成读取数据的模式
                //5.将缓冲区中的数据再写入到通道
                outChannel.write(buf);
                //清空缓冲区
                buf.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if ( outChannel != null) {
                try {
                    outChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inChannel!=null) {
                try {
                    inChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos!=null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis!=null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

NIO_Pipe管道

给管道加锁 tryLock

package com.nio;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.concurrent.TimeUnit;

public class NIOchannelLock {
	public static void main(String[] args) throws IOException, InterruptedException {
		FileOutputStream fos=new FileOutputStream("a.txt");
		FileChannel channel=fos.getChannel();
		//然后给管道加锁
		FileLock lock=channel.tryLock();
		//判断锁是否添加成功
		if(lock!=null) {
			System.out.println("channel加锁成功");
			TimeUnit.SECONDS.sleep(10);
			//解锁
			lock.release();
			System.out.println("解锁成功");
		}
	}
}

服务端ServerSocketChannel

package com.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestServerSocketChannel {
	public void start() throws IOException {
		//创建线程池 固定长度的线程池
		//线程池种类: 固定长度。单例(只有一个线程)。基于缓存的
		ExecutorService threadpool=Executors.newFixedThreadPool(10);//10个线程池
		//创建服务端通道
		ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
		//设置通道是否为阻塞。
		serverSocketChannel.configureBlocking(false);
		//设置服务端端口号
		serverSocketChannel.bind(new InetSocketAddress(ServerInfo.PORT));
		//创建选择器
		Selector select=Selector.open();
		//第二个参数表示注册的时机  有读取数据的时机  写入数据的时机 请求连接就注册 
		serverSocketChannel.register(select, SelectionKey.OP_ACCEPT);//表示请求的时候就注册到选择器
		//定义一个操作状态,读 写 请求 的返回值 做比较
		int requestStatus=0;//所有的操作状态都是大于0的
		//如果状态码大于0,表示已经进行了操作
		while(select.select()>0) {
			//但是我们不知道操作了什么。获得所有的状态码。
			Set<SelectionKey> selectedKeys=select.selectedKeys();
			//把状态码进行遍历.迭代器
			Iterator<SelectionKey> iterator =selectedKeys.iterator();
			while(iterator.hasNext()) {
				//拿到集合中存在的 选择器的key
				SelectionKey next=iterator.next();
				//判断是否是连接状态
				if(next.isAcceptable()) {
					//处理连接请求  返回的是连接对象  套接字通道
					SocketChannel  socketChannel=serverSocketChannel.accept();
					//如果不等于空 连接成功
					if(socketChannel!=null) {
						threadpool.submit(new ThreadNio(socketChannel));
					}
				}
			}
		}
		threadpool.shutdown();//终结线程池   这个关闭表示 温柔关闭 如果当前线程池内有正在运行的线程。.等待所有线程运行完在关闭  
		//threadPool.shutdownNow();//强硬关闭 如果线程池内还有任务 未执行的 移除队列 已经在执行的 尝试停止
		serverSocketChannel.close();
	}
	public static void main(String[] args) throws IOException {
		new TestServerSocketChannel().start();
	}
}

服务端线程run方法ThreadNio

package com.selector;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class ThreadNio implements Runnable {
	private SocketChannel  socketChannel;
	private boolean flag=true;
	

	public ThreadNio(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
	}
	@Override
	public void run() {
	ByteBuffer bytebuffer=ByteBuffer.allocate(1024);
	try {
		
		while (flag) {
			bytebuffer.clear();
			int count = this.socketChannel.read(bytebuffer);
			//将读取到的信息转为字符串
			String readMessage = new String(bytebuffer.array(), 0, count);
			System.out.println("客户端发送的信息" + readMessage);
			String writeMessage = "服务器发送的信息" + readMessage;
			if ("exit".equalsIgnoreCase(readMessage)) {
				System.out.println("[拜拜!]");
				flag = false;
			}
			bytebuffer.clear();
			bytebuffer.put(writeMessage.getBytes());
			bytebuffer.flip();
			this.socketChannel.write(bytebuffer);
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
	try {
		this.socketChannel.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
	}

}

客户端SocketChannel

package com.selector;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Client {
	public static void main(String[] args) throws IOException {
		//获得一个客户端通道 
		SocketChannel  socketChannel=SocketChannel.open(new InetSocketAddress(ServerInfo.ADDRESS, ServerInfo.PORT));
		//是否为阻塞模式
		//socketChannel.configureBlocking(false);
		//创建缓存区
		ByteBuffer buffer=ByteBuffer.allocate(1024);
		while(true) {
			buffer.clear();
			String str=InputUtil.getInput("请输入信息");
			buffer.put(str.getBytes());
			buffer.flip();
			socketChannel.write(buffer);
			buffer.clear();
			if("exit".equals(str)) {
				break;
			}
			int data=socketChannel.read(buffer);
			System.out.println(new String(buffer.array(),0,data));
		}
		socketChannel.close();
	}
}

选择器 的应用Selector

 

inputUtil工具类

package com.selector;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputUtil {
	public static BufferedReader READER=new BufferedReader(new InputStreamReader(System.in));
	public static String getInput(String str){
		String result="";
		if("".equals(result) || result==null) {
			System.out.println(str);
			try {
				result=READER.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值