طلب مني صديقي مساعدتي في كتابة برنامج لاستيراد البيانات من مستند نصي إلى قاعدة بيانات Oracle. ليس من الصعب تقنيا. تم إصلاح تنسيق المستند. طالما أن التحليل الميداني المقابل في قاعدة البيانات يكفي ، فإن المفتاح يكمن في الأداء.
حجم البيانات كبير وملايين السجلات. لذلك ، بالنظر إلى أنك بحاجة إلى استخدام التنفيذ المتزامن متعدد الخيوط ، وتواجه مشاكل أثناء عملية الكتابة ، أريد حساب إجمالي الوقت الذي تقضيه في جميع عمليات الطفل بعد الانتهاء من التنفيذ. سجل الوقت الحالي قبل إنشاء عملية الطفل الأولى. استخدم System.CurrentTimeMillis () لتسجيل الوقت الحالي بعد اكتمال عملية الطفل الأخيرة. الفرق الزمني الذي تم الحصول عليه عن طريق الطرح مرتين هو إجمالي الوقت. الرمز كما يلي
tstart long = system.currentTimeMillis () ؛ System.out.println (thread.currentThread (). getName () + "start") ؛ // طباعة علامة البدء لـ (int ii = 0 ؛ ii <threadnum ؛ ii ++) {// open threads runnable r = new RunNable () // افعل شيئًا ... ... system.out.println (thread.currentThread (). getName () + "end.") ؛ }} thread t = new thread (r) ؛ T.Start () ؛ } system.out.println (thread.currentThRead (). getName () + "end.") ؛ // print end tag tend = system.currentTimeMillis () ؛ System.out.println ("Total Time:" + (Tend - tstart) + "millions") ؛ والنتيجة هي أن العبارات التي يستخدمها الخيط الرئيسي لطباعة إجمالي الوقت يتم تنفيذها تقريبًا لحظة نهايات الحلقة. والسبب هو أن جميع خيوط الأطفال يتم تنفيذها بشكل متزامن ، ويتم تشغيل الخيط الرئيسي أيضًا عند تشغيلها ، مما يطرح سؤالاً: كيفية "جعل الخيط الرئيسي ينتظر تنفيذ جميع مؤشرات الترابط الطفل". حاولت إضافة t.join () بعد بدء كل مؤشر ترابط طفل ، والنتيجة هي أن جميع مؤشرات الترابط تنفذ بالتتابع ، مما يفقد معنى التزامن ، وهو ما لا أريده.
لم تجد Google حلاً عبر الإنترنت لفترة طويلة. ألم يواجه أحد مثل هذه الحاجة؟ أم أن هذه المشكلة بسيطة للغاية؟ كان على وو ناي التفكير في حل نفسه ...
أخيرًا ، يتمثل الحل الخاص بي في تخصيص وراثي فئة الاستيراد من java.lang.thread ، والتحميل الزائد طريقة Run () ، واستخدام خاصية قائمة لحفظ جميع مؤشرات الترابط التي تم إنشاؤها. وبهذه الطريقة ، طالما أنك تحكم على ما إذا كانت القائمة فارغة ، فستعرف ما إذا كانت هناك خيوط أطفال لم يتم تنفيذها. رمز الفصل كما يلي:
يمتد الفئة العامة ImportThread Thread {Private Static List <froof> RunningThreads = New ArrayList <froof> () ؛ Public ImportThread () {} Override public void Run () {chigistration (this) ؛ // register system.out.println (thread.currentThread (). getName () + "start ...") "End.") ؛ // print the end tag} تسجيل void public (موضوع t) {synchronized (runnathreads) {runningthreads.add (t) ؛ }} public void unregist (thread t) {synchronized (runnthreads) {synchronized (runnthreads) {runningthreads.remove (t) ؛ }} static boolean hasthroadRunning () {return (rundhreads.size ()> 0) ؛ // عن طريق الحكم على ما إذا كان الجري فارغًا ، يمكنك معرفة ما إذا كانت هناك مؤشرات ترابط لم يتم تنفيذها}} رمز في الموضوع الرئيسي:
tstart long = system.currentTimeMillis () ؛ System.out.println (thread.currentTherD (). getName ()+"start") ؛ // طباعة علامة البدء لـ (int ii = 0 ؛ ii <threadnum ؛ ii ++) {// Open Threads thread t = new ImportThread () ؛ T.Start () ؛ } بينما (صحيح) {// في انتظار جميع مؤشرات الترابط الطفل لإكمال التنفيذ إذا (! importThread.hasThReadRunning ()) {break ؛ } thread.sleep (500) ؛ } system.out.println (thread.currentThRead (). getName () + "end.") ؛ // print end tag tend = system.currentTimeMillis () ؛ System.out.println ("Total Time:" + (Tend - tstart) + "millions") ؛نتيجة الطباعة هي:
البداية الرئيسية
الموضوع 1 يبدأ ...
الموضوع 5 يبدأ ...
الموضوع -0 يبدأ ...
الموضوع 2 يبدأ ...
الموضوع 3 يبدأ ...
الموضوع 4 يبدأ ...
Thread-5 نهايات.
Thread-4 نهايات.
Thread-2 ينتهي.
Thread-0 نهايات.
Thread-3 نهايات.
ينتهي الموضوع -1.
نهاية الرئيسية.
إجمالي الوقت: 20860 مليون
يمكنك أن ترى أن الخيط الرئيسي يبدأ التنفيذ فقط بعد تنفيذ جميع مؤشرات الترابط الطفل.
================================================================== =================================================================
تحتوي الطريقة أعلاه على خطر مخفي: في حالة بدء تشغيل الخيط 1 وينتهي ، ولم تبدأ مؤشرات الترابط الأخرى بعد ، فإن حجم التشكيلات الجارية هو أيضًا 0 ، سيعتقد الخيط الرئيسي أن جميع مؤشرات الترابط قد تم تنفيذها. يتمثل الحل في استبدال Type Type Runnateds بعداد نوع غير بسيط ، ويجب تعيين قيمة العداد قبل إنشاء مؤشر الترابط.
فئة MyCountdown
الطبقة العامة mycountdown {private int count ؛ public myCountDown (int count) {this.count = count ؛ } العد التنازلي المزامنة العامة المزامنة () {count-- ؛ } hasnext boolean المزامنة العامة () {return (count> 0) ؛ } public int getCount () {return count ؛ } public void setCount (int count) {this.count = count ؛ }} فئة الاستيراد
يمتد فئة public eSportThread thread {private mycountdown c ؛ Public ImportThread (MyCountDown C) {this.c = c ؛ } Override public void run () {system.out.println (thread.currentThread (). getName () + "ابدأ ...") ؛ // طباعة علامة البدء // افعل شيئًا نهاية العلامة}} في الموضوع الرئيسي
System.out.println (thread.currentTherAd (). getName ()+"start") ؛ // طباعة علامة البدء myCountdown c = new myCountDown (threadnum) ؛ // تهيئة العد التنازلي لـ (int ii = 0 ؛ ii <threadnum ؛ ii ++) {// Open Twhelds thow ther thor ther therehread (c) ؛ T.Start () ؛ } بينما (صحيح) {// في انتظار تنفيذ جميع مؤشرات الترابط الطفل if (! c.hasNext ()) } system.out.println (thread.currentThread (). getName () + "end.") ؛ // طباعة علامة النهايةنتيجة الطباعة:
البداية الرئيسية
الموضوع 2 يبدأ ...
الموضوع 1 يبدأ ...
الموضوع -0 يبدأ ...
الموضوع 3 يبدأ ...
الموضوع 5 يبدأ ...
الموضوع 4 يبدأ ...
Thread-5 نهايات. 5 مزيد من المواضيع
ينتهي الموضوع -1. هناك 4 مواضيع أخرى
Thread-4 نهايات. هناك 3 مواضيع أخرى
Thread-2 ينتهي. 2 مزيد من المواضيع
Thread-3 نهايات. 1 موضوع لا يزال هناك
Thread-0 نهايات. هناك 0 خيوط متبقية
نهاية الرئيسية.
طريقة أسهل: استخدم java.util.concurrent.countdownlatch بدلاً من mycountdown ، استخدم طريقة Await () بدلاً من (True) {...}
فئة الاستيراد
يمتد الاستيراد الفئة العامة Thread {private CountDownLatch ThreadsSignal ؛ Public ImportThread (CountDownLatch ThreadsSignal) {this.threadsSignal = threadsSignal ؛ } Override public void run () {system.out.println (thread.currentThRead (). getName () + "start ...") ؛ // افعل شيئًا threadssignal.countdown () ؛ // يتم تقليل العداد بمقدار 1 في نهاية نظام الموضوع. }} في الموضوع الرئيسي
CountDownLatch ThreadSignal = new CountdownLatch (threadnum) ؛ // تهيئة العد التنازلي لـ (int ii = 0 ؛ ii <threadnum ؛ ii ++) {// Open Threads Iterator Final <Tring> Itt = it.get (ii) ؛ Thind T = new ImportThread (ITT ، SQL ، ThreadSignal) ؛ T.Start () ؛ } threadsignal.await () ؛ // في انتظار جميع مؤشرات الترابط الطفل لإكمال نظام التنفيذ.نتيجة الطباعة:
البداية الرئيسية
الموضوع 1 يبدأ ...
الموضوع -0 يبدأ ...
الموضوع 2 يبدأ ...
الموضوع 3 يبدأ ...
الموضوع 4 يبدأ ...
الموضوع 5 يبدأ ...
Thread-0 نهايات. 5 مزيد من المواضيع
ينتهي الموضوع -1. هناك 4 مواضيع أخرى
Thread-4 نهايات. هناك 3 مواضيع أخرى
Thread-2 ينتهي. 2 مزيد من المواضيع
Thread-5 نهايات. 1 موضوع لا يزال هناك
Thread-3 نهايات. هناك 0 خيوط متبقية
نهاية الرئيسية.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.