JAVA IO/NIOå¦ä¹ ç¬è®°
æç« ç®å½
- JAVA IO/NIOå¦ä¹ ç¬è®°
-
- ç¬è®°é¾æ¥
- 1. JAVA IO/NIO
-
- 1.1 ç®åä»ç»
- 1.2é»å¡åéé»å¡
- 1.3 Linux ç½ç» I/O模åï¼åç½®ç¥è¯ï¼
-
- é»å¡IO模å
- éé»å¡IO模å
- å¤è·¯å¤ç¨IO模å
- ä¿¡æ¯é©±å¨IO模å
- å¼æ¥IO模å
- äºç§IO对æ¯
- 1.4 NIO
-
- 认è¯NIO
- 认è¯channel
- 认è¯Buffer
- 认è¯Selector
- FileChannel使ç¨
-
- è·åFilechannelçæ¹æ³
- FileChannel读åæ°æ®
- ä»FileChannelåæ°æ®
- Charset使ç¨
-
- è·å解ç å¨å¯¹è±¡
- è·åç¼ç å¨å¯¹è±¡
- SocketChannelåServerSocketChannel使ç¨
-
- å建SocketChannel
- å建ServerSocketChannel
- é»å¡åéé»å¡çåæ¢
- SocketChanneléé»å¡å¼
- Selector使ç¨
-
- å建Selector
- 注åChannelå°Selector
- 轮询channel
ç¬è®°é¾æ¥
JVMå¦ä¹ ç¬è®°ï¼ä¸ï¼
JVMå¦ä¹ ç¬è®°ï¼äºï¼
JVMå¦ä¹ ç¬è®°ï¼ä¸ï¼
JVMå¦ä¹ ç¬è®°ï¼åï¼
ï¼å¾ æ´æ°â¦ï¼
JAVA NIO
ï¼å¾ æ´æ°â¦ï¼
1. JAVA IO/NIO
1.1 ç®åä»ç»
NIOå³New IOï¼æ¯å¨JDK1.4ä¸æå¼å ¥çãNIO主è¦ç¨å°çæ¯åï¼æ以NIOçæçè¦æ¯IOé«å¾å¤ãNIO åä¼ ç» IO ä¹é´ç¬¬ä¸ä¸ªæ大çåºå«æ¯ï¼IO æ¯é¢åæµçï¼NIO æ¯é¢åç¼å²åºçãNIO主è¦æ¯ä½¿ç¨Selectorå¤è·¯å¤ç¨å¨æ¥å®ç°ãSelectorå¨Linuxç主æµæä½ç³»ç»ä¸æ¯éè¿epollå®ç°çã
1.2é»å¡åéé»å¡
é»å¡å
Java IOçåç§æµæ¯é»å¡çãè¿æå³çï¼å½ä¸ä¸ªçº¿ç¨è°ç¨read() æ write()æ¶ï¼è¯¥çº¿ç¨è¢«é»å¡ï¼ç´å°æä¸äºæ°æ®è¢«è¯»åï¼ææ°æ®å®å ¨åå ¥ã该线ç¨å¨æ¤æé´ä¸è½å干任ä½äºæ äºãå ¸åçé»å¡ IO çä¾å为ï¼data = socket.read();å¦ææ°æ®æ²¡æ就绪ï¼å°±ä¼ä¸ç´é»å¡å¨ read æ¹æ³ã
éé»å¡å
Java NIOçéé»å¡æ¨¡å¼ï¼ä½¿ä¸ä¸ªçº¿ç¨ä»æééåé请æ±è¯»åæ°æ®ï¼ä½æ¯å®ä» è½å¾å°ç®åå¯ç¨çæ°æ®ï¼å¦æç®å没ææ°æ®å¯ç¨æ¶ï¼å°±ä»ä¹é½ä¸ä¼è·åï¼èä¸æ¯ä¿æ线ç¨é»å¡ï¼æ以ç´è³æ°æ®åçå¯ä»¥è¯»åä¹åï¼è¯¥çº¿ç¨å¯ä»¥ç»§ç»åå ¶ä»çäºæ ã
1.3 Linux ç½ç» I/O模åï¼åç½®ç¥è¯ï¼
é»å¡IO模å
ä¼ ç»çIO模åï¼è¯»åè¿ç¨é½ä¼åçé»å¡ç°è±¡ãå½ç¨æ·çº¿ç¨ååº IO 请æ±ä¹åï¼å æ ¸ä¼å»æ¥çæ°æ®æ¯å¦å°±ç»ªï¼å¦æ没æ就绪就ä¼çå¾ æ°æ®å°±ç»ªï¼èç¨æ·çº¿ç¨å°±ä¼å¤äºé»å¡ç¶æï¼è¿å ¥é»å¡éåï¼ï¼ç¨æ·çº¿ç¨äº¤åº CPUãå½æ°æ®å°±ç»ªä¹åï¼å æ ¸ä¼å°æ°æ®æ·è´å°ç¨æ·çº¿ç¨ï¼å¹¶è¿åç»æç»ç¨æ·çº¿ç¨ï¼ç¨æ·çº¿ç¨æè§£é¤ block ç¶æã
ä¸äºç¸å ³å¾ç
éé»å¡IO模å
ä¸ä¸ªçº¿ç¨ä»æééåé请æ±è¯»åæ°æ®ï¼ä½æ¯å®ä» è½å¾å°ç®åå¯ç¨çæ°æ®ï¼å¦æç®å没ææ°æ®å¯ç¨æ¶ï¼å°±ä»ä¹é½ä¸ä¼è·åï¼èä¸æ¯ä¿æ线ç¨é»å¡ï¼æ°æ®è¿æ²¡æåå¤å¥½æ¶ï¼çº¿ç¨ä¼ç»§ç»åç读å请æ±ï¼ä¸æ¦å æ ¸ä¸çæ°æ®åå¤å¥½äºï¼å¹¶ä¸åå次æ¶å°äºç¨æ·çº¿ç¨ç请æ±ï¼é£ä¹å®é©¬ä¸å°±å°æ°æ®æ·è´å°äºç¨æ·çº¿ç¨ï¼ç¶åè¿åãä½æ¯å¯¹äºéé»å¡ IO å°±æä¸ä¸ªé常严éçé®é¢ï¼å¨ while 循ç¯ä¸éè¦ä¸æå°å»è¯¢é®å æ ¸æ°æ®æ¯å¦å°±ç»ªï¼è¿æ ·ä¼å¯¼è´ CPU å ç¨çé常é«ã
ç¸å ³å¾ç
å¤è·¯å¤ç¨IO模å
Java NIO å®é ä¸å°±æ¯å¤è·¯å¤ç¨ IOãå¨å¤è·¯å¤ç¨ IO 模åä¸ï¼åªéè¦ä½¿ç¨ä¸ä¸ªçº¿ç¨å°±å¯ä»¥ç®¡çå¤ä¸ªsocketï¼ç³»ç»ä¸éè¦å»ºç«æ°çè¿ç¨æè 线ç¨ï¼ä¹ä¸å¿ ç»´æ¤è¿äºçº¿ç¨åè¿ç¨ï¼å¹¶ä¸åªæå¨çæ£æsocket 读åäºä»¶è¿è¡æ¶ï¼æä¼ä½¿ç¨ IO èµæºï¼æ以å®å¤§å¤§åå°äºèµæºå ç¨ãå½ç¨æ·è¿ç¨è°ç¨äºselectï¼é£ä¹æ´ä¸ªè¿ç¨ä¼è¢«blockï¼èåæ¶ï¼kernelä¼âçè§âææselectè´è´£çsocketï¼å½ä»»ä½ä¸ä¸ªsocketä¸çæ°æ®åå¤å¥½äºï¼selectå°±ä¼è¿åãè¿ä¸ªæ¶åç¨æ·è¿ç¨åè°ç¨readæä½ï¼å°æ°æ®ä»kernelæ·è´å°ç¨æ·è¿ç¨ãå¦å¤å¤è·¯å¤ç¨ IO 为ä½æ¯éé»å¡ IO 模åçæçé«æ¯å 为å¨éé»å¡ IO ä¸ï¼ä¸æå°è¯¢é® socket ç¶ææ¶éè¿ç¨æ·çº¿ç¨å»è¿è¡çï¼èå¨å¤è·¯å¤ç¨ IO ä¸ï¼è½®è¯¢æ¯ä¸ª socket ç¶ææ¯å æ ¸å¨è¿è¡çï¼è¿ä¸ªæçè¦æ¯ç¨æ·çº¿ç¨è¦é«çå¤ã
ç¸å ³å¾çï¼
ä¿¡æ¯é©±å¨IO模å
å¨ä¿¡å·é©±å¨ IO 模åä¸ï¼å½ç¨æ·çº¿ç¨åèµ·ä¸ä¸ª IO 请æ±æä½ï¼ä¼ç»å¯¹åºç socket 注åä¸ä¸ªä¿¡å·å½æ°ï¼ç¶åç¨æ·çº¿ç¨ä¼ç»§ç»æ§è¡ï¼å½å æ ¸æ°æ®å°±ç»ªæ¶ä¼åéä¸ä¸ªä¿¡å·ç»ç¨æ·çº¿ç¨ï¼ç¨æ·çº¿ç¨æ¥æ¶å°ä¿¡å·ä¹åï¼ä¾¿å¨ä¿¡å·å½æ°ä¸è°ç¨ IO 读åæä½æ¥è¿è¡å®é ç IO 请æ±æä½ã
ç¸å ³å¾çï¼
å¼æ¥IO模å
å¼æ¥IOæ¯ææçæ³ç IO 模åï¼å¼æ¥IOæ§è¡è¿ç¨ï¼
- ç¨æ·çº¿ç¨åèµ· read æä½ã
- å æ ¸æ¥åå°ä¸ä¸ª asynchronous read ä¹åï¼ç«å»è¿åï¼è¯´æ read 请æ±å·²ç»æååèµ·äºãï¼åªæ¯åç¥çº¿ç¨ï¼ææ¶å°äºä½ ç读å请æ±å¦ï¼
- ç¨æ·çº¿ç¨ä¸ä¼äº§çä»»ä½ blockï¼ç¨æ·çº¿ç¨ç»§ç»å¹²èªå·±çäºæ ã
- å æ ¸ä¼çå¾ æ°æ®åå¤å®æï¼ç¶åå°æ°æ®æ·è´å°ç¨æ·çº¿ç¨ï¼å½è¿ä¸åé½å®æä¹åï¼å æ ¸ä¼ç»ç¨æ·çº¿ç¨åéä¸ä¸ªä¿¡å·ï¼åè¯å® read æä½å®æäºã
- ç¨æ·çº¿ç¨è¢«åç¥æä½å®æåå»è¯»åæ°æ®ã
å¨ç¨æ·çº¿ç¨çæ¥ï¼åªéè¦å åèµ·ä¸ä¸ªè¯·æ±ï¼å½æ¥æ¶å æ ¸è¿åçæåä¿¡å·æ¶è¡¨ç¤º IO æä½å·²ç»å®æï¼å¯ä»¥ç´æ¥å»ä½¿ç¨æ°æ®äºã
è·ä¿¡å·é©±å¨IO对æ¯ï¼ä¿¡å·é©±å¨IOåªæ¯ç±å æ ¸éç¥æ们åéå¯ä»¥å¼å§ä¸ä¸ä¸ªIOæä½ï¼èå¼æ¥IO模åæ¯ç±å æ ¸éç¥æ们æä½ä»ä¹æ¶åå®æï¼IOå ¨ç±å æ ¸å ¨é¨å¤çãå¼æ¥IOï¼å æ ¸ä¼ä¸»å¨å°æ°æ®å¤å¶å°ç¨æ·è¿ç¨/线ç¨ãä¹å°±æ¯è¯´ï¼å¨å¼æ¥ IO 模åä¸ï¼æ¶å°ä¿¡å·è¡¨ç¤º IO æä½å·²ç»å®æï¼ä¸éè¦åå¨ç¨æ·çº¿ç¨ä¸è°ç¨ IO å½æ°è¿è¡å®é ç读åæä½ã
注æï¼å¼æ¥ IO æ¯éè¦æä½ç³»ç»çåºå±æ¯æï¼å¨ Java 7 ä¸ï¼æä¾äº Asynchronous IOã
ç¸å ³å¾çï¼
äºç§IO对æ¯
IOè¿ç¨å¯ä»¥åå为ï¼çå¾ æ°æ®å°è¾¾ï¼æ°æ®è¯»åè¿ç¨ã两大æ¶é´æ®µã
ä»ä¸é¢çå¾å¯ä»¥åç°ï¼
é»å¡IO模åï¼ é»å¡æ¶é´æé¿ã
éé»å¡IO模åï¼ CPUæ¶è大ï¼ä¸æcheck浪费CPUèµæºã
å¤è·¯å¤ç¨IO模å: å ç¨èµæºå°ï¼ä½¿ç¨ä¸ä¸ªçº¿ç¨ç®¡çå¤ä¸ªsocketï¼ã
ä¿¡æ¯é©±å¨IO模åï¼ éè¿æ³¨åä¿¡å·å½æ°ï¼å æ ¸åå¤å¥½æ°æ®åï¼åéä¿¡æ¯åç¥æ§è¡ä¸ä¸æ¥IOã
å¼æ¥IO模åï¼ IOå ¨ç¨äº¤ç±å æ ¸å¤çï¼ç¨æ·ç¨åºåªéåéIO请æ±ï¼ç¶åçå¾ å æ ¸åç¥IOå®æå³å¯ã
1.4 NIO
认è¯NIO
JDK1.4å¼å§å¼å ¥äºNIOç±»åºï¼NIO主è¦æ¯ä½¿ç¨Selectorå¤è·¯å¤ç¨å¨æ¥å®ç°ï¼NIO 主è¦æä¸å¤§æ ¸å¿é¨åï¼
- Channel(éé)
- Buffer(ç¼å²åº)
- Selector
ä¼ ç» IO åºäºåèæµåå符æµè¿è¡æä½ï¼è NIO åºäº Channel å Buffer(ç¼å²åº)è¿è¡æä½ï¼æ°æ®æ»æ¯ä»éé读åå°ç¼å²åºä¸ï¼æè ä»ç¼å²åºåå ¥å°ééä¸ãJava IO é¢åæµæå³çæ¯æ¬¡ä»æµä¸è¯»ä¸ä¸ªæå¤ä¸ªåèï¼ç´è³è¯»åææåèï¼å®ä»¬æ²¡æ被ç¼åå¨ä»»ä½å°æ¹ãNIO çç¼å²å¯¼åæ¹æ³ä¸åãæ°æ®è¯»åå°ä¸ä¸ªå®ç¨åå¤ççç¼å²åºï¼éè¦æ¶å¯å¨ç¼å²åºä¸åå移å¨ãè¿å°±å¢å äºå¤çè¿ç¨ä¸ççµæ´»æ§ã
模åå¾
认è¯channel
Channel å IO ä¸ç Stream(æµ)æ¯å·®ä¸å¤çãåªä¸è¿ Stream æ¯ååçï¼èChannel æ¯ååçï¼æ¢å¯ä»¥ç¨æ¥è¿è¡è¯»æä½ï¼åå¯ä»¥ç¨æ¥è¿è¡åæä½ãNIO ä¸ç Channel ç主è¦å®ç°æï¼
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
åä¸ä¸ªç¨äºç½ç»éä¿¡ï¼SocketChannelåServerSocketChannelç¨äºTCPè¿æ¥ï¼DatagramChannelç¨äºUDPè¿æ¥ã
认è¯Buffer
Channel æä¾ä»æ件ãç½ç»è¯»åæ°æ®çæ¸ éï¼ä½æ¯è¯»åæåå ¥çæ°æ®é½å¿ é¡»ç»ç± BufferãBufferï¼å®é ä¸æ¯ä¸ä¸ªè¿ç»æ°ç»ã
常ç¨ç Buffer çåç±»æï¼ByteBufferãIntBufferã CharBufferã LongBufferã DoubleBufferãFloatBufferãShortBufferã
ææç¼å²åºé½æ4个å±æ§ï¼capacityãlimitãpositionãmarkã
- Capacity 容éï¼å³å¯ä»¥å®¹çº³çæ大æ°æ®éï¼å¨ç¼å²åºå建æ¶è¢«è®¾å®å¹¶ä¸ä¸è½æ¹å
- Limit 表示ç¼å²åºçå½åç»ç¹ï¼ä¸è½å¯¹ç¼å²åºè¶ è¿æéçä½ç½®è¿è¡è¯»åæä½ãä¸æéæ¯å¯ä»¥ä¿®æ¹ç
- Position ä½ç½®ï¼ä¸ä¸ä¸ªè¦è¢«è¯»æåçå ç´ çç´¢å¼ï¼æ¯æ¬¡è¯»åç¼å²åºæ°æ®æ¶é½ä¼æ¹åæ¹å¼ï¼ä¸ºä¸æ¬¡è¯»åä½åå¤
- Mark æ è®°ï¼è°ç¨mark()æ¥è®¾ç½®mark=positionï¼åè°ç¨reset()å¯ä»¥è®©positionæ¢å¤å°æ è®°çä½ç½®
å ³äºByteBufferç±»å®ä¾å
ByteBufferç±»æä¾äº4个éæå·¥åæ¹æ³æ¥è·å¾ByteBufferçå®ä¾ã
- allocate(int capacity) ä»å 空é´ä¸åé ä¸ä¸ªå®¹é大å°ä¸ºcapacityçbyteæ°ç»ä½ä¸ºç¼å²åºçbyteæ°æ®åå¨å¨
- allocateDirect(int capacity) æ¯ä¸ä½¿ç¨JVMå æ èæ¯éè¿æä½ç³»ç»æ¥å建å ååç¨ä½ç¼å²åºï¼å®ä¸å½åæä½ç³»ç»è½å¤æ´å¥½çè¦åï¼å æ¤è½è¿ä¸æ¥æé«I/Oæä½é度ãä½æ¯åé ç´æ¥ç¼å²åºçç³»ç»å¼éå¾å¤§ï¼å æ¤åªæå¨ç¼å²åºè¾å¤§å¹¶é¿æåå¨ï¼æè éè¦ç»å¸¸éç¨æ¶ï¼æ使ç¨è¿ç§ç¼å²åº
- wrap(byte[] array) è¿ä¸ªç¼å²åºçæ°æ®ä¼åæ¾å¨byteæ°ç»ä¸ï¼bytesæ°ç»æbuffç¼å²åºä»»ä½ä¸æ¹ä¸æ°æ®çæ¹å¨é½ä¼å½±åå¦ä¸æ¹ãå ¶å®ByteBufferåºå±æ¬æ¥å°±æä¸ä¸ªbytesæ°ç»è´è´£æ¥ä¿åbufferç¼å²åºä¸çæ°æ®ï¼éè¿allocateæ¹æ³ç³»ç»ä¼å¸®ä½ æé ä¸ä¸ªbyteæ°ç»
- wrap(byte[] array, int offset, int length) å¨ä¸ä¸ä¸ªæ¹æ³çåºç¡ä¸å¯ä»¥æå®å移éåé¿åº¦ï¼è¿ä¸ªoffsetä¹å°±æ¯å è£ åbyteBufferçpositionï¼èlengthå¢å°±æ¯limit-positionç大å°ï¼ä»èæ们å¯ä»¥å¾å°limitçä½ç½®ä¸ºlength+position(offset)
认è¯Selector
Selector ç±»æ¯ NIO çæ ¸å¿ç±»ï¼Selector è½å¤æ£æµå¤ä¸ªæ³¨åçééä¸æ¯å¦æäºä»¶åçï¼å¦ææäºä»¶åçï¼ä¾¿è·åäºä»¶ç¶åé对æ¯ä¸ªäºä»¶è¿è¡ç¸åºçååºå¤çãè¿æ ·ä¸æ¥ï¼åªæ¯ç¨ä¸ä¸ªå线ç¨å°±å¯ä»¥ç®¡çå¤ä¸ªééï¼ä¹å°±æ¯ç®¡çå¤ä¸ªè¿æ¥ã
FileChannel使ç¨
è·åFilechannelçæ¹æ³
éè¿FileInputStream/FileOutputStreamè·å
//éè¿FileInputStream/FileOutputStreamè·å
File file =new File("./src/testchannl.txt");
FileInputStream fin = new FileInputStream(file.getAbsoluteFile());
FileChannel fcl = fin.getChannel();
éè¿FileChannelçopenæ¹æ³
//éè¿FileChannelçopenæ¹æ³,opené»è®¤ä¸ºè¯»æ¨¡å¼æå¼
Path path = Paths.get("./src/testchannl.txt");
FileChannel channel = FileChannel.open(path);
//å模å¼æå¼
channel = FileChannel.open(path, StandardOpenOption.WRITE);
FileChannel读åæ°æ®
éç´æ¥ç¼å²åº
//ç³è¯·buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//clear bufferä¸çæ°ç»,å
¶å®æ¯éè¿æ¹åpositionçæ°å¼è¿è¡ä¼ªå é¤çï¼å¹¶æªçæ£çå é¤æ°æ®
byteBuffer.clear();
while (fileChannel.read(byteBuffer)>0){
//åæ¢ï¼æ´æ¹limit=position,position=0ï¼ä¸»è¦ç®çæ¯è¦éå®ææçæ°æ®å
byteBuffer.flip();
byte[] tem = new byte[byteBuffer.limit()];
//è·åæ°æ®
byteBuffer.get(tem);
System.out.print(new String(tem));
byteBuffer.clear();
}
éè¿å åæ å°æ件
//---------------------éè¿å
åæ å°æ件-----------------
//读å
¥æ¨¡å¼æå¼éé
inchannel = FileChannel.open(path, StandardOpenOption.READ);
//è·åæ å°æ件
MappedByteBuffer mapBuffer = inchannel.map(FileChannel.MapMode.READ_ONLY,0,inchannel.size());
byte[] dst = new byte[mappedByteBuffer.limit()];
//ä»æ å°æ件è°ç¨getæ¹æ³åå°dstä¸
mappedByteBuffer.get(dst);
System.out.println(new String(dst));
ä»FileChannelåæ°æ®
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
String data = new String("hello world!");
byteBuffer.put(data.getBytes());//åå°buffer
byteBuffer.flip(); //åæ¢
channel.write(byteBuffer);//åå
¥éé
byteBuffer.clear();//éç½®positionålimitï¼çå¾
ä¸æ¬¡ç读å
Charset使ç¨
Charset为å符é对象
//è·åææå¯ä»¥å符é
Charset.availableCharsets();
//è·åé»è®¤å符é
Charset.defaultCharset();
è·å解ç å¨å¯¹è±¡
Charset charset = Charset.forName(charsetname);
charset.newDecoder();
è·åç¼ç å¨å¯¹è±¡
Charset charset = Charset.forName(charsetname);
charset.newEncoder();
SocketChannelåServerSocketChannel使ç¨
å建SocketChannel
//æ¹å¼ä¸
SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1",12345));
//æ¹å¼äº
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("127.0.0.1",12345));
å建ServerSocketChannel
//å建并ç»å®å°æå®ç«¯å£
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(12345));
é»å¡åéé»å¡çåæ¢
sc.configureBlocking(false);
ssc.configureBlocking(false);
SocketChanneléé»å¡å¼
sc.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //ç³è¯·ç©ºé´
Scanner scanner = new Scanner(System.in); //æ åè¾å
¥æµï¼é®çï¼
String str = null;
while ((str = scanner.nextLine())!=null){
byteBuffer.put(str.getBytes()); //å°é®çè¾å
¥çæ°æ®æ¾å°bufferä¸
byteBuffer.flip(); //åæ¢ç¶æï¼éå®è¦å
sc.write(byteBuffer); //å°bufferä¸çæ°æ®åå°scä¸
byteBuffer.clear(); //éç½®
}
Selector使ç¨
å建Selector
注åChannelå°Selector
//ServerSocketChannel对象注åå°æå®çselector对象
//SelectionKey.OP_ACCEPT为çæ§äºä»¶
ssc.register(selector, SelectionKey.OP_ACCEPT);
轮询channel
selector.select()