مقدمة
في البرمجة متعددة الخيوط ، من غير الواقعي تعيين مؤشر ترابط لكل مهمة ، والاستهلاك النفقات العامة والموارد لإنشاء مؤشر الترابط مرتفع للغاية. ظهرت برك الخيوط وأصبحت أداة قوية لنا لإدارة المواضيع. من خلال واجهة Executor ، توفر Java طريقة قياسية لفصل عملية تقديم المهمة وتنفيذ العملية ، وتستخدم Runnable لتمثيل المهمة.
بعد ذلك ، دعنا نحلل تنفيذ Java Pool Framework ThreadPoolexecutor.
يعتمد التحليل التالي على JDK1.7
دورة الحياة
في threadpoolexecutor ، يتم استخدام 3 بتات من السعة لتمثيل حالة الجري ، وهي:
1.Running: تلقي مهام جديدة ومهام العملية في قائمة انتظار المهمة
2.shutdown: المهام التي لا تتلقى مهام جديدة ولكن التعامل مع قوائم انتظار المهام
3. التوقف: لم يتم استلام أي مهام جديدة ، ولا يتم إصدار قائمة انتظار مهمة ، ويتم مقاطعة جميع المهام الجارية في نفس الوقت
4.Tiding: تم إنهاء جميع المهام ، وعدد خيوط العمال هو 0. عند الوصول إلى هذه الحالة ، سيتم تنفيذ ().
5. تم إنهاء: تم إنهاء ()
مخطط انتقال الدولة
يتم استخدام الطبقات الذرية لتمثيل أجزاء الدولة في ThreadPoolexecutor
private Final AtomicInteger CTL = New AtomicInteger (CTLOF (Running ، 0)) ؛
نموذج تجمع الموضوع
المعلمات الأساسية
CorePoolsize: الحد الأدنى لعدد خيوط العمال المعيشة (إذا تم تعيين lemtcoreThreadTimeOut ، فإن هذه القيمة هي 0)
MaximumpoolSize: الحد الأقصى لعدد الخيوط ، محدودة حسب السعة
Keepalivetime: وقت البقاء على قيد الحياة للخيط المقابل ، يتم تحديد الوحدة الزمنية بواسطة TimeUnit
Workqueue: قائمة انتظار العمل ، وتخزين المهام التي سيتم تنفيذها
رفض ExecutionHandler: رفض السياسة ، سيتم تشغيل الحد الأقصى لمجموعة مؤشرات الترابط بعد أن تكون تجمع الخيوط ممتلئًا: يتم استخدام الأجزاء الثلاثة الأولى في السعة كبتات العلم ، أي الحد الأقصى لسعة موضوع العامل هو (2^29) -1
أربعة نماذج
CachedThreadPool: تجمع الخيوط القابلة للتخزين المؤقت. إذا تجاوز الحجم الحالي لمجموعة مؤشرات الترابط متطلبات المعالجة ، فسيتم إعادة تدوير مؤشر ترابط الخمول. عندما يزداد الطلب ، يمكن إضافة مؤشرات ترابط جديدة. لا يوجد حد على حجم تجمع الخيوط.
FlexThreadPool: تجمع مؤشر ترابط بحجم ثابت. عند إرسال مهمة ، يتم إنشاء مؤشر ترابط حتى يتم الوصول إلى الحد الأقصى لعدد تجمعات الخيوط. في هذا الوقت ، لن يتغير حجم تجمع الخيوط.
SingleThreadPool: تجمع مؤشرات ترابط واحد ، والذي يحتوي على مؤشر ترابط عامل واحد فقط لتنفيذ المهام. يمكن أن يضمن تنفيذ المهام بشكل متسلسل بالترتيب الذي تكون فيه في قائمة الانتظار. إذا انتهى هذا الموضوع بشكل غير طبيعي ، فسيتم إنشاء مؤشر ترابط جديد لتنفيذ المهام.
ScurdeThReadPool: تجمع مؤشر ترابط ثابت الحجم ويؤدي المهام بطريقة تأخر أو توقيت ، على غرار المؤقت.
تنفيذ تنفيذ المهمة
المنطق الأساسي:
1. العدد الحالي من مؤشرات الترابط <corePoolsize ، افتح مباشرة مؤشر الترابط الأساسي الجديد لتنفيذ Addworker Task (الأمر ، صحيح)
2. العدد الحالي من المواضيع> = corepoolsize ، ويتم إضافة المهمة بنجاح إلى قائمة انتظار العمل
1). تحقق مما إذا كانت الحالة الحالية لمجموعة الخيوط قيد التشغيل
2). إذا لم يكن الأمر كذلك ، يتم رفض المهمة
3). إذا كان الأمر كذلك ، فحدد ما إذا كان العدد الحالي من مؤشرات الترابط هو 0. إذا كان 0 ، أضف مؤشر ترابط عامل.
3. قم بتشغيل Addworker Task Corde Offection لتنفيذ مؤشرات الترابط (الأمر ، خطأ) ، ورفض المهمة إذا فشلت في البدء. من التحليل أعلاه ، يمكننا تلخيص المراحل الأربع لتشغيل تجمع الخيوط:
1) .poolsize <corepoolsize وقائمة الانتظار فارغة. سيتم إنشاء موضوع جديد لمعالجة المهام المقدمة.
2) .poolsize == corepoolsize. في هذا الوقت ، تدخل المهمة المقدمة في قائمة انتظار العمل. يحصل مؤشر ترابط العامل على تنفيذ المهمة من قائمة الانتظار. في هذا الوقت ، قائمة الانتظار ليست فارغة وليست ممتلئة.
3) .poolsize == corepoolsize وقائمة الانتظار ممتلئة. سيتم أيضًا إنشاء مؤشر ترابط جديد لمعالجة المهمة المقدمة ، ولكن تجمع <maxpoolsize
4) .poolsize == maxpoolsize وقائمة الانتظار ممتلئة ، وسيتم تشغيل سياسة الرفض
سياسة الرفض <br /> ذكرنا سابقًا أنه إذا تعذر تنفيذ المهمة ، فسيتم رفضها. DesideDexecutionHandler هي واجهة التعامل مع المهام المرفوضة. فيما يلي أربع استراتيجيات للرفض.
Abortpolicy: السياسة الافتراضية ، إنهاء المهمة ، رمي الرفض
CallerRunspolicy: قم بتنفيذ المهمة الحالية في مؤشر ترابط المتصل دون إلقاء استثناءات
DiscardPolicy: تجاهل السياسة ، وتجاهل المهمة مباشرة ، ولا ترمي الاستثناءات
di scandolderspolicy: التخلي عن أقدم مهمة ، وتنفيذ المهمة الحالية ، ولا ترمي استثناءات
العامل في تجمع الخيوط
عامل يرث التجريدي upplyseuedsynchronizer و rannable. السابق يوفر للعامل وظيفة قفل ، ويقوم الأخير بتنفيذ الطريقة الرئيسية لسلاسل المواضيع العامل Runworker (Worker W) (تنفيذ المهمة المفاجئة من قائمة انتظار المهمة). تم العثور على مراجع العمال في جمع العمال وهي محمية بواسطة Mainlock.
reentrantlock النهائي الخاص = جديد reentrantlock () ؛
Hashset النهائي الخاص <Worker> العمال = new Hashset <Former> () ؛
Core Function Runworker
فيما يلي المنطق المبسط ، ملاحظة: يقوم تشغيل كل مؤشر ترابط العامل بتنفيذ الوظائف التالية
Runworker النهائي void (عامل W) {thread wt = thread.currentThRead () ؛ TASK RUNNABLE = W.FIRSTTASK ؛ W.FirstTask = null ؛ بينما (المهمة! = null || (task = getTask ())! = null) {w.lock () ؛ قبل Execute (WT ، Task) ؛ Task.Run () ؛ apherexecute (المهمة ، ألقيت) ؛ W.Unlock () ؛ } processworkerexit (w ، excedabrectly) ؛} 1. احصل على المهمة من getTask ()
2. قفل العامل
3. تنفيذ extexecute (WT ، Task) ، وهي طريقة التمديد التي توفرها ThreadPoolexecutor إلى الفئات الفرعية
4. تشغيل المهمة. إذا قام العامل بتكوين المهمة الأولى ، فسيتم تنفيذ المهمة الأولى أولاً وفقط.
5. تنفيذ effexecute (المهمة ، ألقيت) ؛
6. فتح العامل
7. إذا كانت المهمة التي تم الحصول عليها لاغية ، أغلق العامل
احصل على مهمة getTask
قائمة انتظار المهمة داخل تجمع الخيوط عبارة عن قائمة انتظار حظر ، والتي يتم تمريرها أثناء البناء.
plockequeue النهائي الخاص <Runnable> workqueue ؛
GetTask () يحصل على المهمة من قائمة انتظار المهمة ، ويدعم الحظر والمهلة في انتظار المهام. ستؤدي أربع مواقف إلى إرجاع NULL وإغلاق العامل.
1. عدد المواضيع الموجودة يتجاوز الحد الأقصى لعدد المواضيع
2. تجمع الخيوط في حالة توقف
3. تجمع الخيوط في حالة الإغلاق وقائمة انتظار العمل فارغة
4. مهلة مهمة انتظار الخيوط ، وعدد المواضيع يتجاوز عدد مؤشرات الترابط المحتجزة
المنطق الأساسي: توقيت أو منع مهمة الانتظار في قائمة انتظار الحظر. سيؤدي توقيت مهمة الانتظار إلى إغلاق مؤشر ترابط العامل.
توقيت = ALTERCORETHREADTIMEOUT || wc> corepoolsize ؛ runnable r = timed؟ workqueue.poll (keepalivetime ، timeunit.nanoseconds): workqueue.take () ؛
في انتظار المهمة ، سيصبح الوقت في حالتين:
1. السماح لخيوط الأساس بانتظار المهلة ، أي allowcoreThreadTimeout (صحيح)
2. الخيط الحالي هو مؤشر ترابط طبيعي ، في هذا الوقت wc> corepoolsize
يستخدم قائمة انتظار العمل blockingqueue ، لذلك لن أقوم بتوسيعه هنا. سأكتب تحليلًا مفصلاً لاحقًا.
لخص
يعتمد ThreadPoolexecutor على نموذج المنتج المستهلك. إن تشغيل المهام في تقديم ما يعادل المنتج ، وخيط تنفيذ المهام يعادل المستهلك.
يوفر المنفذون أربع طرق لبناء نموذج تجمع مؤشرات الترابط استنادًا إلى ThreadPoolexecutor. بالإضافة إلى ذلك ، يمكننا أن نرث مباشرة Threadpoolexecutor وإعادة كتابة طرق exerexecute و efterexecute لتخصيص عملية تنفيذ مهمة مجموعة مؤشرات الترابط.
يجب مراعاة قوائم الانتظار المحدودة أو قوائم الانتظار غير المحدودة وفقًا للوضع المحدد ، ويجب أيضًا النظر في حجم قائمة انتظار العمل وعدد مؤشرات الترابط بعناية.
يوصى باستخدام سياسة الرفض لاستخدام CallerRunspolicy ، والتي لا تتخلى عن المهمة أو ترمي استثناء ، ولكن بدلاً من ذلك تراجع المهمة إلى مؤشر ترابط المتصل للتنفيذ.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.