تصف هذه المقالة تنزيل Java متعدد الخيوط. شاركه للرجوع إليه ، على النحو التالي:
يمكن أن يؤدي استخدام الملفات متعددة الخيوط لتنزيل الملفات إلى إكمال تنزيل الملفات بشكل أسرع. السبب في أن الملفات متعددة الخيوط سريعة هو أنها تشغل الكثير من موارد الخادم. على سبيل المثال: افترض أن الخادم يخدم ما يصل إلى 100 مستخدم في نفس الوقت ، ويتوافق مؤشر ترابط واحد في الخادم مع مستخدم واحد. لا يتم تنفيذ 100 مؤشرات الترابط بشكل متزامن في الكمبيوتر ، ولكن يتم تنفيذها بدورها بواسطة وحدة المعالجة المركزية. إذا كان التطبيق A يستخدم 99 سلسلة سلسلة لتنزيل الملفات ، فهذا يعادل احتلال موارد 99 مستخدمًا. لنفترض أن متوسط وقت التنفيذ المخصص من قبل وحدة المعالجة المركزية لكل مؤشر ترابط في ثانية واحدة هو 10 مللي ثانية. يحصل التطبيق A على وقت تنفيذ 990ms في ثانية واحدة في الخادم ، في حين أن التطبيقات الأخرى لا تحتوي إلا على 10 مللي ثانية في وقت واحد في ثانية واحدة. تمامًا مثل صنبور ، عندما يكون ناتج المياه في الثانية متساوية ، فإنه بالتأكيد أكثر من الماء مقابل 990 ميلي ثانية مقارنة بـ 10 مللي ثانية.
عملية تنفيذ التنزيل متعدد الخيوط:
1. احصل أولاً على طول الملف الذي تم تنزيله ، ثم قم بتعيين طول الملف المحلي.
httpurlconnection.getContentLength () ؛ randomaccessfile file = new RandomAccessFile ("youdao.exe" ، "rw") ؛ file.setLength (filesize) ؛ // قم بتعيين طول الملف المحلي2. احسب طول البيانات وموقع تنزيل كل مؤشر ترابط بناءً على طول الملف وعدد مؤشرات الترابط. على سبيل المثال: طول الملف هو 6 أمتار وعدد مؤشرات الترابط هو 3 ، ثم طول البيانات التي تم تنزيلها بواسطة كل مؤشر ترابط هو 2M ، والموقع الذي يبدأ فيه كل مؤشر ترابط في التنزيل في الشكل أدناه.
3. استخدم حقل رأس النطاق في HTTP لتحديد مكان بدء التنزيل من كل مؤشر ترابط ، مثل: تحديد تنزيل الملف من الموضع 2M للملف ، يكون الرمز كما يلي:
نسخة الكود كما يلي: httpurlconnection.setRequestProperty ("Range" ، "Bytes = 2097152-") ؛
4. احفظ الملف واستخدم فئة RandomAccessFile لتحديد المكان الذي يبدأ فيه كل مؤشر ترابط في كتابة البيانات من الملف المحلي.
RandomAccessFile threadfile = new randomaccessfile ("<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 وبدء بدء التشغيل تحت d: /tomcat/apache-tomcat-7.0.37/bin
1.Downloadtest.java
package www.csdn.net.down ؛ import java.io.file ؛ import java.io.fileinputstream ؛ import java.io.fileOutputStream ؛ import java.io.ioException ؛ import java.io.inputstream ؛ import java.io.randomaccessfile java.net.malformedUrlexception ؛ import java.net.url ؛ فئة عامة تحميل tloadtest {file public file ؛ وصول عشوائي عام. // عدد المواضيع العامة static int threadnum = 3 ؛ // كل مؤشر ترابط مسؤول عن تنزيل int blocksize ؛ // قم بإنشاء مسار Access Public String Path = "http: // localhost: 8080/doudou/youdao.exe" ؛ public static int threadcount ؛ // Quantity public void testDown () {try {// إنشاء url url url url url = url new url (path) ؛ // إنشاء httpurlconnection كائن httpurlConnection httpurlConnection = (httpurlconnection) url .openconnection () ؛ // قم بتعيين طريقة إرسال الطلبات httpurlConnection.SetRequestMethod ("get") ؛ // تعيين ما إذا كانت مهلة الطلب httpurlConnection.setConnectTimeout (5000) ؛ // set httpurlconnection .SetRequestProperty ("user-Agent" ، "Mozilla/5.0 (Compatible ؛ MSIE 10.0 ؛ Windows NT 6.2 ؛ Trident/6.0)") ؛ // ما إذا كانت الاستجابة ناجحة إذا (httpurlConnection.getResponsecode () == 200) {// احصل على حجم الملف int size = httpurlconnection.getContentLength () ؛ System.out.println ("حجم الملف" + حجم) ؛ // إنشاء ملف ملف = ملف جديد ("youdao.exe") ؛ AccessFile = new RandomAccessFile (ملف ، "RWD") ؛ // اضبط حجم الملف AccessFile.setLength (الحجم) ؛ // قم بتنزيل حجم كل مؤشر ترابط clocksize = size / threadnum ؛ // افتح ثلاثة مؤشرات ترابط لتشغيل هذا الملف لـ (int i = 1 ؛ i <= threadnum ؛ i ++) {// 1 2 3 // قم بحساب موضع البداية لكل مؤشر ترابط int startize = (i - 1) * blockize ؛ // end position int ينتهي = (i) * blockize ؛ // عندما يكون مؤشر الترابط هو آخر مؤشر ترابط إذا كان (i == threadnum) {// تحديد ما إذا كان حجم الملف أكبر من الموضع النهائي المحسوب إذا انتهى (حجم>) {// أن الموضع النهائي يساوي حجم الملف = الحجم ؛ }} // قم بإنشاء قراءة عشوائية لكل مؤشر ترابط RandomAccessFile threadAccessFile = new RandomAccessFile (ملف ، "RWD") ؛ موضوع جديد (تنزيل جديد (I ، ThreadAccessFile ، يبدأ ، ينتهي ، المسار)). start () ؛ }}} catch (malformedurlexception e) {// todo catch catch e.printstacktrace () ؛ } catch (ioException e) {// todo acto catch block e.printstacktrace () ؛ }} public static void main (string [] args) {downloadTest downloadTest = new downloadTest () ؛ // استدعاء طريقة التنزيل downloadTest.testDown () ؛ }} class downloadTramThread تنفذ RunNable {// تغليف تنزيل ملف public RandomAccessFile AccessFile ؛ // كل مؤشر ترابط يحتوي على كائن ملف AccessFile Thread1 Thread2 Thread3 // وضع بدء تشغيل ملف ترابط ملف تنزيل Public Int ؛ الانتهاء العام ينتهي ؛ // مسار مسار الملف تنزيل مسار السلسلة العامة ؛ الجمهور int threadid ؛ . this.AccessFile = AccessFile ؛ this.startSize = يبدأ ؛ this.endize = ينتهي ؛ this.path = path ؛ } Override public void run () {// تنفيذ طريقة التشغيل ، جرب {// إنشاء ملف file threadfile = new file (threadid + ".txt") ؛ if (threadfile.exists ()) {// اقرأ محتوى الملف // قم بإنشاء كائن دفق إدخال الملف FileInputStream fis = جديد fileInputStream (threadfile) ؛ // استخدم فئة الأدوات لقراءة بيانات البايت [] = dreamtools.istodata (FIS) ؛ // تحويل إلى سلسلة string threadlen = سلسلة جديدة (بيانات) ؛ if ((threadlen! = null) && (! " // حل الخطأ من 416BUG إذا انتهى (يبدأ>) }}} // إنشاء url url url url url = url جديد (مسار) ؛ // إنشاء httpurlconnection كائن httpurlConnection httpurlConnection = (httpurlconnection) url .openconnection () ؛ // قم بتعيين رأس الطلب httpurlconnection.setRequestMethod ("get") ؛ // تعيين ما إذا كانت مهلة الطلب httpurlConnection.setConnectTimeout (5000) ؛ // set httpurlconnection .SetRequestProperty ("user-Agent" ، "Mozilla/5.0 (Compatible ؛ MSIE 10.0 ؛ Windows NT 6.2 ؛ Trident/6.0)") ؛ // إعدادات المفاتيح httpurlconnection.setRequestProperty ("المدى" ، "bytes =" + startize + "-" + ينتهي) ؛ // إخراج نظام الموضوع الحالي. // استجابة ناجحة // قم بتعيين موضع البدء في ملفات القراءة العشوائية Accessfile.keek (startize) ؛ // احصل على إدخال كائن الدفق المقابل هو = httpurlConnection.getInputStream () ؛ // إنشاء مخزن بايت دفق الإخراج [] = بايت جديد [1024] ؛ int len = 0 ؛ int threadtotal = 0 ؛ // حفظ السجل بعد تنزيل كل مؤشر ترابط/ بينما ((len = iS.Read (buffer))! = -1) {Accessfile.write (buffer ، 0 ، len) ؛ ThreadTotal += len ؛ // قم بتسجيل الطول الذي تكتبه // xml file // قم بتسجيل طول الملف من خلال ملف fileOutputStream fos = جديد fileOutputStream (threadfile) ؛ fos.write ((threadtotal + "") .getBytes ()) ؛ fos.flush () ؛ fos.close () ؛ } accessfile.close () ؛ is.close () ؛ System.out.println (ThreadId + "تنفيذ مؤشر الترابط") ؛ // تشغيل مؤشر الترابط Synchronized (downloadTest.class) {downloadtest.threadcount ++ ؛ if (downloadTest.ThreadCount> = downloadtestest.threadnum) {for (int i = 1 ؛ i <= downloadTest.threadNum ؛ i ++) {file file = file new (i+". txt") ؛ if (file.exists ()) {file.delete () ؛ }}}}} catch (malformedurlexception e) {// todo catch catch e.printstacktrace () ؛ } catch (ioException e) {// todo acto catch block e.printstacktrace () ؛ }}}2. StreamTools.Java تغليف أدوات البث
package www.csdn.net.down ؛ import java.io.bytearrayoutputstream ؛ import java.ioexception ؛ import java.io.inputstream ؛ public class Streamtools {public static byte [] iStodata (inputStream is) {// bytearraytream byteartream = // منطقة المخزن المؤقت لقراءة Byte Byte Buffer [] = New Byte [1024] ؛ // قراءة السجل طول int len = 0 ؛ // قراءة الحلقة بينما ((len = is.read (buffer))! = -1) {bops.write (buffer ، 0 ، len) ؛ } // تحويل محتوى القراءة إلى بيانات بايت بايت بايت [] = bops.tobytearray () ؛ bops.flush () ؛ bops.close () ؛ is.close () ؛ إرجاع البيانات ؛ }}آمل أن يكون هذا المقال مفيدًا لبرمجة Java للجميع.