Java NIO总结Word文档格式.docx
《Java NIO总结Word文档格式.docx》由会员分享,可在线阅读,更多相关《Java NIO总结Word文档格式.docx(17页珍藏版)》请在冰点文库上搜索。
Read(读取请求信息)、Send(发送响应信息)。
非I/O事件包括encode、compute、decode。
异步连接池:
首先,用户处理线程调用连接池对象的某个方法(比如sendRequest),把一个能够标识本次请求的Request对象扔给连接池。
之后用户处理线程可以去做别的事情,比如,向其他连接池发送请求。
最后当用户线程处理完能做的业务逻辑后,就可以等待连接池返回结果了。
(一)读写IO:
(按块缓冲区)
packagejava.nio.io;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.nio.ByteBuffer;
importjava.nio.MappedByteBuffer;
importjava.nio.channels.FileChannel;
importjava.util.Date;
/**
*@Project:
NIO
*@Title:
CopyFile.java
*@Package
*@Description:
JAVANIO读取写入文件方面优势
*@authorpaul.wei2011@
*@dateMay16,20139:
51:
13AM
*@versionV1.0
*/
//传统IO一直是性能瓶颈,因为每次按字节读取,耗费磁头寻址次数,磁头寻址时间是固定的,次数多耗费时间就长
publicclassCopyFile{
publicstaticvoidmain(String[]args)throwsException{
Stringinfile="
C:
\\copy.sql"
;
Stringoutfile="
\\copy.txt"
//获取源文件和目标文件的输入输出流
FileInputStreamfin=newFileInputStream(infile);
FileOutputStreamfout=newFileOutputStream(outfile);
//获取输入输出通道
FileChannelfcin=fin.getChannel();
//FileChannel对象是线程安全的
FileChannelfcout=fout.getChannel();
//每个FileChannel都有一个叫'
fileposition'
的概念,该position值决定文件中哪一处的数据接下来被读或写。
//FileChannelposition是从底层文件描述符获取的,当字节被read()或write()方法传输时,文件position会自动更新。
//MappedByteBuffer类使得我们可以通过ByteBufferAPI来访问数据文件
byteBuffer(fcin,fcout);
//2秒
mapByteBuffer(fcin,fcout);
//1秒
}
//创建缓冲区
publicstaticvoidbyteBuffer(FileChannelfcin,FileChannelfcout)throwsIOException{
ByteBufferbuffer=ByteBuffer.allocate(1024);
//MappedByteBuffermapBuffer=fcin.map(FileChannel.MapMode.READ_ONLY,0,fcin.size());
Datestart=newDate();
while(true){
//clear方法重设缓冲区,使它可以接受读入的数据
buffer.clear();
//从输入通道中将数据读到缓冲区
intr=fcin.read(buffer);
//read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1
if(r==-1){
break;
//flip方法让缓冲区可以将新读入的数据写入另一个通道
buffer.flip();
//将缓冲区内容写入输出通道
fcout.write(buffer);
Dateend=newDate();
System.out.println("
150MbyteBufferspend:
"
+(end.getTime()-start.getTime())/1000+"
sec"
);
//150M4秒
}
//创建映射缓冲区,把文件的内容被映像到计算机虚拟内存的一块区域,
//这样就可以直接操作内存当中的数据而无需操作的时候每次都通过I/O去物理硬盘读取文件
publicstaticvoidmapByteBuffer(FileChannelfcin,FileChannelfcout)throwsIOException{
MappedByteBuffermapBuffer=fcin.map(FileChannel.MapMode.READ_ONLY,0,fcin.size());
Datestart=newDate();
fcout.write(mapBuffer);
//将映射缓冲区直接写入输出通道
Dateend=newDate();
System.out.println("
150MmapByteBufferspend:
}
(二)异步IO:
●传统IO:
服务端:
publicclassSynchServerSocket{
privateintport=8821;
privateServerSocketserverSocket;
privateExecutorServiceexecutorService;
//线程池
privatefinalintPOOL_SIZE=10;
//单个CPU线程池大小
publicSynchServerSocket()throwsIOException{
serverSocket=newServerSocket(port);
//Runtime的availableProcessor()方法返回当前系统的CPU数目.
executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
服务器启动"
publicvoidservice(){
while(true){
Socketsocket=null;
try{
//接收客户连接,只要客户进行了连接,就会触发accept();
从而建立连接,
//如果客户端未连接,服务端一直阻塞I/O等待连接,多线程从而耗费CPU及栈资源
socket=serverSocket.accept();
executorService.execute(newHandler(socket));
}catch(Exceptione){
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args)throwsIOException{
newSynchServerSocket().service();
//服务启动一直等待连接
classHandlerimplementsRunnable{
privateSocketsocket;
publicHandler(Socketsocket){
this.socket=socket;
privatePrintWritergetWriter(Socketsocket)throwsIOException{//根据socket获取输出流
OutputStreamsocketOut=socket.getOutputStream();
returnnewPrintWriter(socketOut,true);
privateBufferedReadergetReader(Socketsocket)throwsIOException{//根据socket获取输入流
InputStreamsocketIn=socket.getInputStream();
returnnewBufferedReader(newInputStreamReader(socketIn));
publicStringecho(Stringmsg){
return"
echo:
+msg;
publicvoidrun(){
try{
Newconnectionaccepted"
+socket.getInetAddress()+"
:
+socket.getPort());
BufferedReaderbr=getReader(socket);
PrintWriterpw=getWriter(socket);
Stringmsg=null;
while((msg=br.readLine())!
=null){
System.out.println(msg);
pw.println(echo(msg));
if(msg.equals("
bye"
))
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(socket!
=null)
socket.close();
客户端:
publicclassSynchClientSocket{
publicstaticvoidmain(String[]args){
intnumTasks=10;
ExecutorServiceexec=Executors.newCachedThreadPool();
for(inti=0;
i<
numTasks;
i++){
exec.execute(newTask(i));
classTaskimplementsRunnable{
privateSocketsocket=null;
publicfinalinttaskId=0;
privateinttaskID;
publicTask(inttaskID){
this.taskID=taskID;
@Override
publicvoidrun(){
Task"
+taskID+"
start"
try{
socket=newSocket("
localhost"
port);
//发送关闭命令
OutputStreamsocketOut=socket.getOutputStream();
socketOut.write("
shutdown\r\n"
.getBytes());
//接收服务器的反馈
BufferedReaderbr=newBufferedReader(newInputStreamReader(socket.getInputStream()));
Stringmsg=null;
while((msg=br.readLine())!
=null)
response:
+msg);
}catch(IOExceptione){
●异步IO(多路复用,通知模式)
publicclassAsynServerimplementsRunnable{
privateByteBufferr_buff=ByteBuffer.allocate(1024);
privateByteBufferw_buff=ByteBuffer.allocate(1024);
privatestaticintport=8848;
publicAsynServer(){
newThread(this).start();
try{
//多路复用:
Selector各种IO事件注册到Selector,事件发生通知,不同通道对象注册到Selector
Selectorselector=Selector.open();
//生成一个服务端口通道ssc
ServerSocketChannelssc=ServerSocketChannel.open();
//将侦听端设为异步方式
ssc.configureBlocking(false);
//将服务端口通道ssc绑定一个端口
ssc.socket().bind(newInetSocketAddress(port));
//将服务端口通道注册到selector上监听事件为OP_ACCEPT信号
ssc.register(selector,SelectionKey.OP_ACCEPT);
echoserverhasbeensetup......"
while(true){
intn=selector.select();
if(n==0){//没有指定的I/O事件发生(监听是否有数据读或写)n>
0,才会有selectedKeys
continue;
}
//当有读或写等任何注册的事件发生时,可以从Selector中获得相应的SelectionKey,同时从SelectionKey
//中可以找到发生的事件和该事件所发生的具体的SocketChannle继承自SelectableChannel,以获得客户端发送过来的数据。
Iteratorit=selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKeykey=(SelectionKey)it.next();
if(key.isAcceptable()){//侦听端信号触发
ServerSocketChannelserver=(ServerSocketChannel)key.channel();
//接受一个新的连接
SocketChannelsc=server.accept();
sc.configureBlocking(false);
//设置该socket的异步信号OP_READ:
当socket可读时,
//触发函数DealwithData();
sc.register(selector,SelectionKey.OP_READ);
}else{
if(key.isReadable()){//某socket可读信号
DealwithData(key);
}
it.remove();
//删除处理过的选择键
it.remove();
}catch(Exceptione){
publicvoidDealwithData(SelectionKeykey)throwsIOException{
intcount;
//由key获取指定socketchannel的引用
SocketChannelsc=(SocketChannel)key.channel();
r_buff.clear();
//读取数据到r_buff
while((count=sc.read(r_buff))>
0);
//确保r_buff可读
r_buff.flip();
//清空写缓存
w_buff.clear();
//将r_buff内容拷入w_buff
w_buff.put(r_buff);
w_buff.flip();
//从写缓冲区向输出通道写之前调用flip
EchoToClient(sc);
publicvoidEchoToClient(SocketChannelsc)throwsIOException{
while(w_buff.hasRemaining())
sc.write(w_buff);
publicstaticvoidmain(Stringargs[]){
if(args.length>
0){
port=Integer.parseInt(args[0]);
newAsynServer();
publicclassAsynClient{
privateSocketChannelsc;
privatefinalintMAX_LENGTH=1024;
privateByteBufferr_buff=ByteBuffer.allocate(MAX_LENGTH);
privateByteBufferw_buff=ByteBuffer.allocate(MAX_LENGTH);
privatestaticStringhost;
publicAsynClient(){
try{
InetSocketAddressaddr=newInetSocketAddress(host,port);
//生成一个socketchannel
sc=SocketChannel.open();
//连接到server
sc.connect(addr);
while(!
sc.finishConnect())
;
connectionhasbeenestablished!
..."
//回射消息
Stringecho;
System.err.println("
Entermsgyou'
dliketosend:
"
BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));
//输入回射消息
echo=br.readLine();
//把回射消息放入w_buff中
w_buff.put(echo.getBytes());
}catch(IOExceptionioe){
sth.iswrongwithbr.readline()"
//发送消息
//进入接收状态
Rec();
//间隔1秒
Thread.currentThread().sleep(1000);
}catch(IOExceptionioe){
ioe.printStackTrace();
catch(InterruptedExceptionie){
ie.printStackTrace();
publicvoidRec()