1. แนวคิดพื้นฐาน
IO เป็นกระบวนการคัดลอกข้อมูลโดยหน่วยความจำหลักและอุปกรณ์ภายนอก (ฮาร์ดดิสก์เทอร์มินัลเครือข่าย ฯลฯ ) IO คือการใช้งานพื้นฐานของระบบปฏิบัติการซึ่งเสร็จสมบูรณ์ผ่านคำสั่ง I/O
ระบบรันไทม์ภาษาทั้งหมดมีเครื่องมือระดับสูงสำหรับการดำเนินการ I/O (PrintfScanf ของ C ซึ่งเป็น encapsulation เชิงวัตถุของ Java)
2. ทบทวน Java Standard IO
ไลบรารีคลาสมาตรฐาน Java IO เป็นสิ่งที่เป็นนามธรรมของ IO Object-oriented จากการดำเนินการตามวิธีการในท้องถิ่นเราไม่จำเป็นต้องให้ความสนใจกับการดำเนินการพื้นฐาน InputStream/OutputStream: ถ่ายโอนหนึ่งไบต์ในแต่ละครั้ง ผู้อ่าน/นักเขียน: หนึ่งอักขระในแต่ละครั้ง
3. บทนำ
NIO เป็นตัวย่อของ Javanewio ซึ่งเป็น API ใหม่ที่ให้ไว้ใน JDK1.4 ลักษณะที่ซันอ้างอย่างเป็นทางการมีดังนี้:
ให้การสนับสนุนแคช (บัฟเฟอร์) สำหรับทุกประเภทดั้งเดิม
โซลูชันการเข้ารหัสและถอดรหัสชุดอักขระ
ช่อง: Abstraction I/O ดั้งเดิมใหม่
รองรับอินเทอร์เฟซการเข้าถึงไฟล์สำหรับไฟล์ล็อคและหน่วยความจำที่แม็พ
ให้ I/O เครือข่ายที่ไม่ปิดกั้นและไม่สามารถปรับขนาดได้สูง
บทความนี้จะเรียนรู้และแนะนำคุณสมบัติเหล่านี้
4. Buffer & Chanel
แชนเนลและบัฟเฟอร์เป็น NIO และเป็นสองสิ่งที่เป็นนามธรรมประเภทข้อมูลพื้นฐานที่สุด
บัฟเฟอร์:
มันเป็นบล็อกของหน่วยความจำอย่างต่อเนื่อง
เป็นสถานที่ขนส่งสำหรับการอ่านหรือการเขียนข้อมูล NIO
ช่อง:
แหล่งที่มาของข้อมูลหรือปลายทางของข้อมูล
อินเทอร์เฟซที่ไม่ซ้ำกันสำหรับการให้ข้อมูลกับบัฟเฟอร์หรือการอ่านข้อมูลบัฟเฟอร์วัตถุบัฟเฟอร์
การสนับสนุน I/O แบบอะซิงโครนัส
ตัวอย่างที่ 1: Copyfile.java:
ตัวอย่างแพ็คเกจ; นำเข้า java.io.fileinputstream; นำเข้า java.io.fileoutputstream นำเข้า java.nio.bytebuffer; นำเข้า java.nio.channels.filechannel; copyfile สาธารณะ "C: //copy.txt"; // รับกระแสอินพุตและเอาต์พุตของไฟล์แหล่งที่มาและเป้าหมาย FileInputStream FIN = ใหม่ FileInputStream (infile); fileOutputStream fout = ใหม่ fileOutputStream (outfile); // รับอินพุต bytebuffer buffer = bytebuffer.allocate (1024); ในขณะที่ (จริง) {// วิธีการล้างจะรีเซ็ตบัฟเฟอร์เพื่อให้สามารถอ่านบัฟเฟอร์ข้อมูลได้ clear (); // อ่านข้อมูลจากช่องอินพุตไปยังบัฟเฟอร์ int r = fcin.read (บัฟเฟอร์); // วิธีการอ่านวิธีการอ่านจำนวนไบต์ อ่านข้อมูลไปยัง Buffer.flip (); // เขียนข้อมูลจากช่องสัญญาณออกไปยังบัฟเฟอร์ fcout.write (บัฟเฟอร์);}}}โครงสร้างภายในของบัฟเฟอร์มีดังนี้ (รูปต่อไปนี้ถูกคัดลอกจากข้อมูล):
รูปที่ 2: โครงสร้างภายในบัฟเฟอร์
บัฟเฟอร์ส่วนใหญ่ควบคุมกระบวนการอ่านและการเขียนโดยสามตัวแปรตำแหน่งขีด จำกัด และความจุ ความหมายของตัวแปรทั้งสามนี้แสดงในตารางต่อไปนี้:
พารามิเตอร์ | โหมดการเขียน | โหมดการอ่าน |
ตำแหน่ง | จำนวนข้อมูลหน่วยที่เขียนในปัจจุบัน | การอ่านตำแหน่งข้อมูลหน่วยปัจจุบัน |
จำกัด | มันแสดงถึงจำนวนสูงสุดของหน่วยข้อมูลและความสามารถที่สามารถเขียนได้เหมือนกัน | มันแสดงถึงจำนวนสูงสุดของหน่วยข้อมูลที่สามารถอ่านได้ซึ่งสอดคล้องกับจำนวนข้อมูลหน่วยที่เขียนก่อน |
ความจุ | ความจุบัฟเฟอร์ | ความจุบัฟเฟอร์ |
วิธีการบัฟเฟอร์ทั่วไป:
flip (): แปลงโหมดการเขียนเป็นโหมดอ่าน
Rewind (): รีเซ็ตตำแหน่งเป็น 0 โดยทั่วไปใช้สำหรับการอ่านซ้ำ
Clear (): ล้างบัฟเฟอร์และเตรียมที่จะเขียนอีกครั้ง (ตำแหน่งกลายเป็น 0 ขีด จำกัด กลายเป็นความจุ)
compact (): คัดลอกข้อมูลที่ยังไม่ได้อ่านไปยังส่วนหัวของบัฟเฟอร์
mark (), รีเซ็ต (): มาร์คสามารถทำเครื่องหมายตำแหน่งรีเซ็ตสามารถรีเซ็ตเป็นตำแหน่งนี้
ประเภทของบัฟเฟอร์ทั่วไป: Bytebuffer, Mappedbytebuffer, Charbuffer, Doublebuffer, Floatbuffer, Intbuffer, Longbuffer, Shortbuffer
ช่องทางทั่วไป: FileChannel, DataGramChannel (UDP), SocketChannel (TCP), ServersocketChannel (TCP)
การทดสอบประสิทธิภาพอย่างง่ายได้ดำเนินการบนเครื่องนี้ แล็ปท็อปของฉันทำงานในปริมาณที่พอเหมาะ (ดูไฟล์แนบสำหรับรหัสเฉพาะดูตัวอย่างด้านล่างในแพ็คเกจ nio.sample.fileCopy) ต่อไปนี้เป็นข้อมูลอ้างอิง:
สถานการณ์ที่ 1: คัดลอกไฟล์ 370m
สถานการณ์ที่ 2: สามเธรดคัดลอกในเวลาเดียวกันแต่ละเธรดจะคัดลอกไฟล์ 370m
ฉาก | FileInputStream+ fileOutputStream | FileInputStream+ bufferedInputStream+ fileOutputStream | Bytebuffer+ FileChannel | Mappedbytebuffer +filechannel |
ฉากหนึ่ง (มิลลิวินาที) | 25155 | 17500 | 19000 | 16500 |
ฉาก 2 เวลา (มิลลิวินาที) | 69000 | 67031 | 74031 | 71016 |
5. nio.charset
การเข้ารหัสและการถอดรหัสอักขระ: ไบต์ตัวเองเป็นเพียงตัวเลขบางตัวซึ่งแยกวิเคราะห์ได้อย่างถูกต้องในบริบทที่ถูกต้อง เมื่อจัดเก็บข้อมูลลงใน Bytebuffer คุณต้องพิจารณาวิธีการเข้ารหัสของชุดอักขระ เมื่ออ่านและแสดงข้อมูล bytebuffer คุณเกี่ยวข้องกับการถอดรหัสชุดอักขระ
java.nio.charset จัดเตรียมชุดของโซลูชั่นสำหรับการเข้ารหัสและการถอดรหัส
รับคำขอ HTTP ที่พบบ่อยที่สุดของเราเป็นตัวอย่างคำขอจะต้องมีการเข้ารหัสอย่างถูกต้องเมื่อร้องขอ การตอบสนองจะต้องถอดรหัสอย่างถูกต้องเมื่อได้รับ
รหัสต่อไปนี้ส่งคำขอไปยัง Baidu และรับผลลัพธ์สำหรับการแสดงผล ตัวอย่างแสดงให้เห็นถึงการใช้ charset
ตัวอย่าง 2Baidureader.java
แพ็คเกจ nio.ReadPage; นำเข้า java.nio.bytebuffer; นำเข้า java.nio.channels.socketChannel; นำเข้า java.nio.charset.charset; นำเข้า java.net.inetsocketaddress; นำเข้า Java.io.ioException; ชุดอักขระส่วนตัว SOCKETNANNEL ช่องสัญญาณโมฆะสาธารณะ readhtmlContent () {ลอง {inetSocketAddress socketAddress = ใหม่ inetSocketAddress ("www.baidu.com", 80); // step1: เปิดช่องทางเชื่อมต่อ = socketchannel.open (socketaddress); http/1.1 " +"/r/n/r/n ")); // step3: อ่านข้อมูล bytebuffer buffer = bytebuffer.allocate (1024); // สร้างบัฟเฟอร์ 1024 -byte ในขณะที่ (channel.read (บัฟเฟอร์)! = -1) {buffer.flip () System.out.println(charset.decode(buffer));// Use Charset.decode method to convert bytes to string buffer.clear();// Clear buffer}}catch (IOException e) {System.err.println(e.toString());} finally {if (channel != null) {try {channel.close();}catch (IOException e) {}}}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ใหม่ baidureader (). readhtmlcontent ();}}6. ไม่มีการปิดกั้น IO
เกี่ยวกับการไม่ปิดกั้น IO เราจะเข้าใจจากแง่มุมของสิ่งที่บล็อกสิ่งที่ไม่ปิดกั้นหลักการที่ไม่ปิดกั้นและ API หลักแบบอะซิงโครนัส
การอุดตันคืออะไร?
กระบวนการสื่อสารเครือข่าย IO ทั่วไปมีดังนี้:
จากกระบวนการสื่อสารเครือข่ายนี้ให้เข้าใจว่าการบล็อกคืออะไร:
หากการเชื่อมต่อไม่ได้มาถึงในกระบวนการข้างต้นการยอมรับจะบล็อกโปรแกรมจะต้องแฮงค์หลังจากทำงานที่นี่และ CPU จะเรียกใช้เธรดอื่นแทน
หากข้อมูลยังไม่พร้อมในกระบวนการข้างต้นการอ่านจะบล็อกด้วย
คุณสมบัติของการปิดกั้นเครือข่าย IO: การเชื่อมต่อหลายเธรด แต่ละเธรดมีพื้นที่สแต็กของตัวเองและใช้เวลา CPU ทุกเธรดจะบล็อกเมื่อพบภายนอกพร้อม ผลลัพธ์ของการปิดกั้นคือมันจะนำไปสู่การสลับบริบทของกระบวนการจำนวนมาก และการสลับบริบทกระบวนการส่วนใหญ่อาจไม่มีความหมาย ตัวอย่างเช่นสมมติว่าเธรดรับฟังพอร์ตและจะมีเพียงไม่กี่คำขอในหนึ่งวัน แต่ CPU จะต้องพยายามสลับบริบทอย่างต่อเนื่องสำหรับเธรดและการสลับส่วนใหญ่สิ้นสุดลงในการปิดกั้น
การไม่ปิดกั้นคืออะไร?
นี่คือคำอุปมา:
บนรถบัสจาก A ถึง B มีหลายจุดบนถนนที่อาจลงไป คนขับไม่ทราบว่าคะแนนใดจะลงจากรถบัส จะจัดการกับผู้ที่ต้องลงรถบัสได้อย่างไร?
1. ในระหว่างกระบวนการคนขับจะถามผู้โดยสารแต่ละคนเป็นประจำว่าเขามาถึงปลายทางหรือไม่ หากมีคนบอกว่าคนขับจะหยุดและผู้โดยสารก็ดับลง (คล้ายกับการบล็อก)
2. ทุกคนบอกผู้ขายตั๋วปลายทางแล้วนอนหลับ คนขับมีปฏิสัมพันธ์กับผู้ขายตั๋วเท่านั้น เมื่อเขามาถึงจุดหนึ่งผู้ขายตั๋วจะแจ้งผู้โดยสารให้ลงรถบัส (คล้ายกับการไม่ปิดกั้น)
เห็นได้ชัดว่าทุกคนไปถึงปลายทางถือได้ว่าเป็นเธรดและไดรเวอร์ถือได้ว่าเป็น CPU ในรูปแบบการปิดกั้นแต่ละเธรดจะต้องสำรวจและสลับบริบทอย่างต่อเนื่องเพื่อให้ได้ผลลัพธ์ของการค้นหาปลายทาง ในโหมดที่ไม่ปิดกั้นผู้โดยสารทุกคน (ด้าย) กำลังนอนหลับ (นอนหลับ) และตื่นขึ้นมาเมื่อสภาพแวดล้อมภายนอกที่แท้จริงพร้อม การปลุกดังกล่าวจะไม่บล็อกอย่างแน่นอน
หลักการของการไม่ปิดกั้น
เปลี่ยนกระบวนการทั้งหมดเป็นงานเล็ก ๆ และทำให้เสร็จสมบูรณ์ผ่านการทำงานร่วมกันระหว่างงาน
เธรดเฉพาะจัดการกิจกรรม IO ทั้งหมดและรับผิดชอบการแจกจ่าย
กลไกที่ขับเคลื่อนด้วยเหตุการณ์: ทริกเกอร์เมื่อเหตุการณ์มาถึงแทนที่จะตรวจสอบเหตุการณ์พร้อมกัน
การสื่อสารเธรด: เธรดสื่อสารผ่านการรอการแจ้งเตือนและวิธีการอื่น ๆ ตรวจสอบให้แน่ใจว่าสวิตช์บริบททุกอย่างเหมาะสม ลดการสลับกระบวนการที่ไม่จำเป็น
ต่อไปนี้เป็นโครงสร้างของ IO แบบอะซิงโครนัส:
เครื่องปฏิกรณ์เป็นบทบาทเชิงเปรียบเทียบข้างต้นของผู้ขายตั๋ว โฟลว์การประมวลผลของแต่ละเธรดน่าจะอ่านข้อมูลถอดรหัสคำนวณการประมวลผลเข้ารหัสและส่งการตอบกลับ
ASYNCHRONOUS IO CORE API
ตัวเลือก
คลาสหลักของ IO แบบอะซิงโครนัสซึ่งสามารถตรวจจับเหตุการณ์ในหนึ่งช่องหรือมากกว่านั้นและแจกจ่ายกิจกรรม
ใช้เธรดเลือกเพื่อฟังเหตุการณ์ในหลายช่องทางและทริกเกอร์การตอบสนองที่สอดคล้องกันตามไดรเวอร์เหตุการณ์ ไม่จำเป็นต้องจัดสรรเธรดสำหรับแต่ละช่อง
การเลือก
มีการเชื่อมโยงของช่องที่สอดคล้องกับข้อมูลสถานะของเหตุการณ์และเวลา
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับเรียงความความรู้พื้นฐาน Java ขั้นพื้นฐานฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!