บทความนี้อธิบายการดาวน์โหลด Java แบบมัลติเธรด แบ่งปันสำหรับการอ้างอิงของคุณดังนี้:
การใช้ไฟล์แบบมัลติเธรดเพื่อดาวน์โหลดไฟล์สามารถดาวน์โหลดไฟล์ได้เร็วขึ้น เหตุผลที่ไฟล์มัลติเธรดมีความรวดเร็วคือพวกเขาครอบครองทรัพยากรเซิร์ฟเวอร์จำนวนมาก ตัวอย่างเช่น: สมมติว่าเซิร์ฟเวอร์ให้บริการผู้ใช้สูงสุด 100 คนในเวลาเดียวกันและหนึ่งเธรดในเซิร์ฟเวอร์สอดคล้องกับผู้ใช้รายหนึ่ง 100 เธรดไม่ได้ดำเนินการพร้อมกันในคอมพิวเตอร์ แต่จะดำเนินการโดย CPU หากแอปพลิเคชัน A ใช้ 99 เธรดเพื่อดาวน์โหลดไฟล์มันจะเทียบเท่ากับการครอบครองทรัพยากรของผู้ใช้ 99 คน สมมติว่าเวลาดำเนินการเฉลี่ยที่จัดสรรโดย CPU ไปยังแต่ละเธรดภายในหนึ่งวินาทีคือ 10ms แอปพลิเคชัน A ได้รับเวลาดำเนินการ 990ms ในหนึ่งวินาทีในเซิร์ฟเวอร์ในขณะที่แอปพลิเคชันอื่น ๆ มีเวลาดำเนินการ 10ms ในหนึ่งวินาที เช่นเดียวกับก๊อกน้ำเมื่อน้ำผลผลิตต่อวินาทีเท่ากับมันเป็นน้ำมากกว่า 990 มิลลิวินาทีมากกว่า 10 มิลลิวินาที
กระบวนการใช้งานการดาวน์โหลดแบบมัลติเธรด:
1. ก่อนอื่นรับความยาวของไฟล์ที่ดาวน์โหลดแล้วตั้งค่าความยาวของไฟล์ท้องถิ่น
httpurlConnection.getContentLength (); file anubctAccessFile = new RandomActEncessFile ("youdao.exe", "rw"); file.setLength (ไฟล์); // ตั้งค่าความยาวของไฟล์ท้องถิ่น2. คำนวณความยาวข้อมูลและตำแหน่งดาวน์โหลดของแต่ละเธรดตามความยาวของไฟล์และจำนวนเธรด ตัวอย่างเช่น: ความยาวของไฟล์คือ 6m และจำนวนเธรดคือ 3 จากนั้นความยาวของข้อมูลที่ดาวน์โหลดโดยแต่ละเธรดคือ 2m และตำแหน่งที่แต่ละเธรดเริ่มดาวน์โหลดจะแสดงในรูปด้านล่าง
3. ใช้ฟิลด์ส่วนหัวช่วงของ HTTP เพื่อระบุว่าแต่ละเธรดเริ่มดาวน์โหลดจากที่ใดเช่น: ระบุการดาวน์โหลดไฟล์จากตำแหน่ง 2M ของไฟล์รหัสมีดังนี้:
การคัดลอกรหัสมีดังนี้: httpurlconnection.setRequestProperty ("ช่วง", "bytes = 2097152-");
4. บันทึกไฟล์และใช้คลาส RandomAccessFile เพื่อระบุตำแหน่งที่แต่ละเธรดเริ่มเขียนข้อมูลจากในไฟล์โลคัล
RandomAccessFile ThreadFile = new RandomActSfile ("<span style =" font-family: Arial, helvetica, sans-serif; "> youdao.exe </span> <span style =" font-family: arial, helvetica, sans-serif; ">", "rw"); ไฟล์ต่อไปนี้เป็นคลาสการใช้งานเฉพาะ:
ก่อนที่จะเขียนคลาสการใช้งานเราต้องวางไฟล์ไว้ก่อนที่จะดาวน์โหลดบนเซิร์ฟเวอร์และปรับใช้:
ฉันใส่ไว้ที่นี่ในไดเรกทอรี d: /tomcat/apache-tomcat-7.0.37/webapps/doudou และเริ่ม startup.bat ภายใต้ d: /tomcat/apache-tomcat-7.0.37/bin
1. downloadtest.java
แพ็คเกจ www.csdn.net.down; นำเข้า java.io.file; นำเข้า java.io.fileinputstream; นำเข้า java.io.fileoutputstream นำเข้า java.io.ioException; นำเข้า Java.io.inputstream; java.net.malformedurlexception; นำเข้า java.net.url; คลาสสาธารณะดาวน์โหลด LoadloadTest {ไฟล์สาธารณะไฟล์; Public RandomaccessFile AccessFile; // จำนวนเธรดสาธารณะคงที่ int threadNum = 3; // แต่ละเธรดมีหน้าที่ดาวน์โหลด int blocksize; // สร้างเส้นทางการเข้าถึงเส้นทางสาธารณะ String = "http: // localhost: 8080/doudou/youdao.exe"; Public Static Int ThreadCount; // ปริมาณโมฆะสาธารณะการทดสอบ () {ลอง {// สร้าง URL Object URL URL = URL ใหม่ (เส้นทาง); // สร้างวัตถุ httpurlconnection httpurlconnection httpurlconnection = (httpurlconnection) url .openconnection (); // ตั้งค่าวิธีการส่งคำขอ httpurlconnection.setRequestMethod ("รับ"); // ตั้งค่าว่าการร้องขอหมดเวลา httpurlconnection.setConnectTimeout (5000); // ตั้งค่า httpurlconnection .setRequestProperty ("ผู้ใช้ตัวแทน", "Mozilla/5.0 (เข้ากันได้; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); // ไม่ว่าการตอบสนองจะสำเร็จถ้า (httpurlConnection.getResponsecode () == 200) {// รับขนาดไฟล์ขนาด int = httpurlConnection.getContentLength (); System.out.println ("ขนาดไฟล์" + ขนาด); // สร้างไฟล์ไฟล์ = ไฟล์ใหม่ ("youdao.exe"); AccessFile = new RandomAccessFile (ไฟล์, "RWD"); // ตั้งค่าขนาดไฟล์ AccessFile.SetLength (ขนาด); // ดาวน์โหลดขนาดของแต่ละเธรด blocksize = size / threadNum; // เปิดสามเธรดเพื่อใช้งานไฟล์นี้สำหรับ (int i = 1; i <= threadNum; i ++) {// 1 2 3 // คำนวณตำแหน่งเริ่มต้นของแต่ละเธรด int เริ่มต้น = (i - 1) * blocksize; // ตำแหน่งสิ้นสุด int สิ้นสุด = (i) * blocksize; // เมื่อเธรดเป็นเธรดสุดท้ายถ้า (i == threadnum) {// กำหนดว่าขนาดไฟล์มากกว่าตำแหน่งสิ้นสุดที่คำนวณได้หรือไม่ถ้า (ขนาด> สิ้นสุด) {// ตำแหน่งสิ้นสุดเท่ากับขนาดไฟล์สิ้นสุด = ขนาด; }} // สร้างการอ่านแบบสุ่มสำหรับแต่ละเธรด RandomActFile threadAccessFile = new RandomAccessFile (ไฟล์, "RWD"); เธรดใหม่ (ใหม่ downloadthread (i, threadaccessfile, startize, สิ้นสุด, path)). start (); }}} catch (malformedurlexception e) {// todo บล็อก catch block ที่สร้างขึ้นอัตโนมัติ e.printstacktrace (); } catch (ioexception e) {// todo บล็อก catch block ที่สร้างอัตโนมัติ e.printstacktrace (); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {downloadtest downloadtest = ใหม่ downloadtest (); // โทรหาวิธีการดาวน์โหลด downloadtest.testdown (); }} คลาส download LoadkThread ดำเนินการ runnable {// encapsulation ของไฟล์ดาวน์โหลด public public randcessfile accessFile; // แต่ละเธรดมีไฟล์ AccessFile File Thread1 Thread2 Thread2 // ตำแหน่งเริ่มต้นของเธรดดาวน์โหลดไฟล์สาธารณะ int เริ่มต้น; สาธารณะสิ้นสุดลง; // พา ธ พา ธ ของไฟล์ดาวน์โหลดพา ธ สตริงสาธารณะ; public int threadid; // การระบุเธรด Public DownloadThread (int threadId, RandomAccessFile AccessFile, int startize, int สิ้นสุด, เส้นทางสตริง) {this.threadId = threadId; this.accessFile = AccessFile; this.tartsize = เริ่มต้น; this.endSize = สิ้นสุด; this.path = path; } @Override โมฆะสาธารณะเรียกใช้ () {// ดำเนินการวิธีการเรียกใช้ลอง {// สร้างไฟล์ไฟล์ threadFile = ไฟล์ใหม่ (threadId + ".txt"); if (threadfile.exists ()) {// อ่านเนื้อหาของไฟล์ // สร้างไฟล์สตรีมอินพุตของไฟล์ FileInputStream FIS = ใหม่ FileInputStream (ThreadFile); // ใช้คลาสเครื่องมือเพื่ออ่านข้อมูลไบต์ [] = StreamTools.istodata (FIS); // แปลงเป็นสตริงสตริง threadLen = สตริงใหม่ (ข้อมูล); if ((threadlen! = null) && (! "". equals (threadlen))) {startize = integer.valueof (threadlen); // แก้ข้อผิดพลาดของ 416bug ถ้า (เริ่มต้น> สิ้นสุด) {startize = สิ้นสุด - 1; }}} // สร้าง URL Object url url = url ใหม่ (เส้นทาง); // สร้างวัตถุ httpurlconnection httpurlconnection httpurlconnection = (httpurlconnection) url .openconnection (); // ตั้งค่าส่วนหัวคำขอ httpurlconnection.setRequestMethod ("รับ"); // ตั้งค่าว่าการร้องขอหมดเวลา httpurlconnection.setConnectTimeout (5000); // ตั้งค่า httpurlconnection .setRequestProperty ("ผู้ใช้ตัวแทน", "Mozilla/5.0 (เข้ากันได้; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); // การตั้งค่าคีย์ httpurlconnection.setRequestProperty ("ช่วง", "bytes =" + เริ่มต้น + "-" + สิ้นสุด); // เอาต์พุตระบบเธรดปัจจุบัน OUT.PRINTLN ("เธรดปัจจุบัน" + ThreadID + "ดาวน์โหลดตำแหน่งเริ่มต้น:" + เริ่ม + "ดาวน์โหลดตำแหน่งสิ้นสุด:" + สิ้นสุด); // การตอบกลับที่ประสบความสำเร็จ // ตั้งตำแหน่งเริ่มต้นของไฟล์อ่านแบบสุ่ม AccessFile.Seek (เริ่มต้น); // รับอินพุทอินพุทออบเจ็กต์วัตถุที่สอดคล้องกันคือ = httpurlConnection.getInputStream (); // สร้างบัฟเฟอร์ไบต์บัฟเฟอร์ Output [] = byte ใหม่ [1024]; int len = 0; int threadtotal = 0; // บันทึกบันทึกหลังจากแต่ละเธรดถูกดาวน์โหลด/ ขณะที่ ((len = is.read (บัฟเฟอร์))! = -1) {accessFile.write (บัฟเฟอร์, 0, len); threadtotal += len; // บันทึกความยาวที่คุณเขียน // xml ไฟล์ // บันทึกความยาวของไฟล์ดาวน์โหลดผ่านไฟล์ fileOutputStream fos = ใหม่ fileOutputStream (ThreadFile); fos.write ((threadtotal + "") .getBytes ()); fos.flush (); fos.close (); } AccessFile.close (); is.close (); System.out.println (ThreadId + "การดำเนินการเธรดเสร็จสมบูรณ์"); // การทำงานของเธรดซิงโครไนซ์ (downloadtest.class) {downloadloadtest.threadcount ++; if (downloadtest.threadcount> = downloadloadtest.threadnum) {สำหรับ (int i = 1; i <= downloadtest.threadnum; i ++) {ไฟล์ไฟล์ = ไฟล์ใหม่ (i+". txt"); if (file.exists ()) {file.delete (); }}}}} catch (malformedurlexception e) {// toDo บล็อก catch block ที่สร้างขึ้นอัตโนมัติ e.printstacktrace (); } catch (ioexception e) {// todo บล็อก catch block ที่สร้างอัตโนมัติ e.printstacktrace (); -2. Streamtools.java encapsulation ของเครื่องมือสตรีมมิ่ง
แพ็คเกจ www.csdn.net.down; นำเข้า java.io.bytearrayoutputstream นำเข้า java.io.ioexception; นำเข้า java.io.inputstream; สตรีมระดับสาธารณะ {สาธารณะคงที่ [] istodata (inputstream) // พื้นที่บัฟเฟอร์สำหรับการอ่านบัฟเฟอร์ข้อมูลไบต์ [] = ไบต์ใหม่ [1024]; // อ่านความยาวบันทึก int len = 0; // วนรอบการอ่านในขณะที่ ((len = is.read (บัฟเฟอร์))! = -1) {bops.write (บัฟเฟอร์, 0, len); } // แปลงเนื้อหาการอ่านเป็นข้อมูลไบต์ไบต์ [] = bops.tobytearray (); bops.flush (); bops.close (); is.close (); ส่งคืนข้อมูล -ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม Java ของทุกคน