وتشارك المواضيع في كثير من الأحيان في العمل. على سبيل المثال ، غالبًا ما يتم تسليم بعض المهام إلى مؤشرات الترابط للتنفيذ غير المتزامن. أو يقوم برنامج الخادم بإنشاء مهمة منفصلة لمعالجة مؤشرات الترابط لكل طلب. ما وراء المواضيع ، مثل اتصال قاعدة البيانات الذي نستخدمه. هذه العمليات الإنشاء أو التدمير أو الفتح والإغلاق لها تأثير كبير على أداء النظام. لذلك ، يتم تسليط الضوء على استخدام "تجمع".
1. لماذا تستخدم تجمع الخيوط
في التنفيذ الموضح في القسم 3.6.1 ، يتم تعيين مؤشر ترابط عامل جديد لكل عميل. عندما يتواصل مؤشر ترابط العامل مع العميل ، يتم تدمير الخيط. طريقة التنفيذ هذه لها أوجه القصور التالية:
• النفقات العامة لإنشاء الخادم وتدميره (بما في ذلك موارد الوقت والموارد) مرتفعة للغاية. لا يلزم شرح هذا العنصر ، يمكنك التحقق من "عملية إنشاء مؤشرات الترابط". بالإضافة إلى العمل الذي تقوم به الماكينة نفسها ، نحتاج أيضًا إلى إنشاء إنشاء وبدء ، والذي يتطلب كل شيء شغل موارد المكدس.
• بالإضافة إلى النفقات العامة لإنشاء وتدمير المواضيع ، تستهلك المواضيع النشطة أيضًا موارد النظام. يجب أن يكون هذا استهلاكًا لموارد المكدس. ويعتبر أيضًا تخمين عدد اتصالات قاعدة البيانات.
• إذا كان عدد مؤشرات الترابط ثابتًا وكان لكل مؤشر ترابط دورة إعلان طويلة ، فسيكون تبديل مؤشر الترابط ثابتًا نسبيًا. أنظمة التشغيل المختلفة لها دورات تبديل مختلفة ، وعادة ما تكون حوالي 20 مللي ثانية. المفتاح المذكور هنا هو نقل حقوق استخدام وحدة المعالجة المركزية بين المواضيع بموجب جدولة JVM ونظام التشغيل الأساسي. إذا تم إنشاء مؤشرات الترابط وتدميرها بشكل متكرر ، فسيتم تبديل مؤشرات الترابط بشكل متكرر ، لأنه بعد تدمير مؤشر الترابط ، يجب إعطاء الحق في استخدام الخيط الجاهز ، بحيث يمكن للمعلومات الحصول على فرصة للتشغيل. في هذه الحالة ، لا يتبع التبديل بين مؤشرات الترابط دورة التبديل الثابتة للنظام ، كما أن النفقات العامة للتبديل أكبر من النفقات العامة للخلق والدمار.
نسبيًا ، باستخدام تجمعات الخيوط ، يتم إنشاء بعض المواضيع مسبقًا ، والتي تزيل المهام باستمرار من قائمة انتظار العمل ثم تنفيذ المهمة. عندما يكمل مؤشر ترابط العامل مهمة واحدة ، يستمر في تنفيذ مهمة أخرى في قائمة انتظار العمل. المزايا هي كما يلي:
• يقلل من عدد الخلق والدمار ، ويمكن إعادة استخدام كل موضوع عامل طوال الوقت ويمكنه أداء مهام متعددة.
• يمكن تعديل عدد المواضيع الموجودة في تجمع الخيوط بسهولة وفقًا لقدرة الاستيعاب للنظام لمنع تعطل النظام بسبب موارد النظام المفرطة.
2. التنفيذ البسيط لمجموعة الخيوط
فيما يلي تجمع خيوط بسيط كتبه بنفسي ، والذي تم رسمه أيضًا مباشرة من كتاب برمجة شبكة Java
Package Thread ؛ Import Java.Util.LinkedList ؛/*** تنفيذ مجموعة مؤشرات الترابط ، استنادًا إلى الطول ، والطول القصوى ، وطول قائمة الانتظار لمجموعة مؤشرات الترابط العادية ، يمكننا زيادة عدد التطبيقات* Author Han*/Public Class MyThreadPool يمتد مجموعة الخيوط {// رقم CPU-وقت التشغيل. getRuntime (). // ما إذا كان سيتم إغلاق المنطق الخاص = خطأ ؛ // Queue Private LinkedList <Runnable> workqueue ؛ // pool pool id private static int threadpoolid ؛ private int threadid ؛ Public MyThreadPool (int poolsize) {super ("mythreadpool."+threadpoolid) ؛ ThreadPoolid ++ ؛ setdaemon (صواب) ؛ WorkQueue = new LinkedList <Runnable> () ؛ لـ (int i = 0 ؛ i <poolsize ؛ i ++) {new workthread (). start () ؛ }} // هنا يمكنك التغيير إلى concurrentLinkEdqueue لتجنب كفاءة استخدام تنفيذ الفراغ العام المتزامن (المهمة القابلة للتشغيل) {if (isclosed) {رمي جديد غير alualalstateException ("تم إغلاق مجموعة التوصيل ...") ؛ } آخر {workqueue.add (Task) ؛ إخطار () ؛ }} محمية GetTask () Runchronible Runnabled Runnable () {بينما (workqueue.size () == 0) {if (isClosed) {return null ؛ } انتظر()؛ } return workqueue.removefirst () ؛ } close void synchronized synchronized () {if (! isclosed) {isClosed = true ؛ workqueue.clear () ؛ المقاطعة () ؛ }} public void join () {synchronized (this) {isClosed = true ؛ إخطار () ؛ } thread [] threads = new thread [activeCount ()] ؛ عدد int = التعداد (المواضيع) ؛ لـ (int i = 0 ؛ i <count ؛ i ++) {try {threads [i] .join () ؛ } catch (استثناء e) {}}} يعمل workthread على توسيع نطاق الخيط {public workthread () {super (mythreadpool.this ، "workthread"+(threadid ++)) ؛ System.out.println ("Create ...") ؛ } Override public void run () {when (! isInterrupted ()) {system.out.println ("run ..") ؛ مهمة Runnable = null ؛ جرب {// هذه مهمة طريقة حظر = getTask () ؛ } catch (استثناء e) {} if (task! = null) {task.run () ؛ } آخر {break ؛ }}}}}}يحدد تجمع الخيوط هذا قائمة انتظار العمل وبعض الخيوط التي تم إنشاؤها مسبقًا. طالما تسمى طريقة التنفيذ ، يمكنك تقديم المهام إلى الموضوع.
عندما لا تكون هناك مهمة ، سيتم حظر الخيط اللاحق في getTask () حتى تأتي مهمة جديدة وتوقظها.
يمكن استخدام كل من الانضمام والإغلاق لإغلاق تجمع الخيوط. الفرق هو أن Join سيكمل المهام في قائمة الانتظار ، في حين أن Close سيقوم على الفور بمسح قائمة الانتظار ويقاطع جميع خيوط العمال. المقاطعة () في الإغلاق () تعادل استدعاء المقاطعة المعنية () التي تحتوي على مؤشرات ترابط الأطفال في مجموعة Threadgroup. لذلك ، عندما ينتظر الخيط أو ينام ، سيتم إلقاء مقاطعة.
فئة الاختبار كما يلي:
الطبقة العامة TestMyThreadPool {public static void main (string [] args) يلقي InterruptedException {mythreadpool pool = new MyThreadPool (3) ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) {pool.execute (new RunNable () {Override public void run () {try {thread.sleep (1000) ؛} catch (interruptedException e) {} system.out.println ("work ...") ؛}}) ؛ } pool.join () ؛ //pool.close () ؛ }}3. تجمع الخيوط المقدمة من مكتبة فئة JDK
يوفر Java تطبيقًا جيدًا لمجموعة الخيوط ، وهو أكثر قوة وفعالية من تنفيذنا ، ولديه وظائف أكثر قوة.
مخطط الفصل هو كما يلي:
لقد قدم كبار السن بالفعل شرحًا جيدًا حول هذا النوع من تجمع الخيوط. لدى أي تجمع خيوط Java تحت Baidu أمثلة مفصلة للغاية ودروس تعليمية مكتوبة ، لذلك لن أكررها هنا.
4. تجمع خيوط حقن الربيع
عند استخدام Spring Framework ، إذا استخدمنا الأساليب التي توفرها Java لإنشاء تجمع مؤشرات ترابط ، فمن غير المريح للغاية إدارة التطبيقات متعددة الخيوط ولا تتوافق مع فكرتنا عن استخدام الربيع. (على الرغم من أن الربيع يمكن حقنه بطرق ثابتة)
في الواقع ، يوفر Spring نفسه أيضًا تنفيذًا جيدًا لمجمعات الخيوط. يسمى هذا الفئة ThreadPooltAskexecutor.
التكوين في الربيع هو كما يلي:
<bean id = "executorservice"> <property name = "corePoolSize" value = "$ {threadpool.corepoolsize}" /> <!-الحد الأدنى لعدد المواضيع المحفوظة بواسطة pool pool-> <property name = "keepaliveseconds name = "maxpoolsize" value = "$ {threadpool.maxpoolsize}" /> <!-الحد الأقصى لعدد مؤشرات الترابط المحفوظة بواسطة pool pool-> <property name = "queuecapacity" value = "$ {threadpool.queuecapacity}" /> <!5. ملاحظات حول استخدام برك الموضوعات
• Deadlock
أي برنامج متعدد مؤشرات الترابط لديه خطر المميت. إن أبسط حالات هي أن اثنين من المواضيع AB ، قفل القفل 1 ، القفل 2 ، B يحمل القفل 2 ، وطلب القفل 1. (سيظهر هذا الموقف أيضًا في قفل MySQL الحصري ، وستقوم قاعدة البيانات بالإبلاغ مباشرة عن رسالة خطأ). هناك طريق مسدود آخر في مجموعة الخيوط: على افتراض أن جميع خيوط العمال في تجمع الخيوط يتم حظرها أثناء تنفيذ مهامها الخاصة ، وهم ينتظرون نتيجة التنفيذ لمهمة معينة أ. المهمة A في قائمة الانتظار ولا يمكن تنفيذها لأنه لا توجد مؤشرات ترابط الخمول. وبهذه الطريقة ، سيتم حظر جميع موارد تجمع الخيوط وسيتم توليد مصلتد.
• موارد النظام غير كافية
إذا كان عدد المواضيع في تجمع الخيوط كبيرًا جدًا ، فستستهلك هذه الخيوط كمية كبيرة من الموارد ، بما في ذلك الذاكرة وموارد النظام الأخرى ، مما يؤثر بشكل خطير على أداء النظام.
• خطأ متزامن
تعتمد قائمة انتظار عمل تجمع الخيوط على طرق WAIT () وإخطار () بتمكين العامل من الحصول على المهام في الوقت المناسب ، ولكن من الصعب استخدام هاتين الطريقتين. إذا كان الكود خاطئًا ، فقد يتم فقد الإخطارات ، مما تسبب في بقاء مؤشر ترابط العامل في وضع الخمول ، متجاهلاً المهام التي يجب معالجتها في قائمة انتظار العمل. لأنه من الأفضل استخدام بعض تجمعات الخيوط الأكثر نضجًا.
• تسرب الموضوع
خطر خطير لاستخدام تجمعات الخيوط هو تسرب الخيط. بالنسبة إلى تجمعات مؤشرات الترابط التي تحتوي على عدد ثابت من مؤشرات ترابط العمال ، إذا كان مؤشر ترابط العامل يلقي بمشاهدة RunTimeException عند تنفيذ مهمة ما ، ولم يتم اكتشاف هذه الاستثناءات أو الأخطاء ، فإن مؤشر ترابط العامل ينتهي بشكل غير طبيعي ، مما يتسبب في فقدان مجموعة مؤشرات الترابط بشكل دائم. (هذا مثير للاهتمام)
موقف آخر هو أن موضوع العامل محظور عند تنفيذ مهمة. إذا كانت تنتظر بيانات إدخال المستخدم ، لكن المستخدم لا يقوم بإدخال البيانات ، مما يؤدي إلى حظر مؤشر الترابط طوال الوقت. هذا موضوع العامل هو بالاسم فقط ، ولا يؤدي في الواقع أي مهام. إذا كانت جميع المواضيع في تجمع الخيوط في هذه الحالة ، فلا يمكن لتجمع مؤشرات الترابط إضافة مهام جديدة.
• التحميل الزائد للمهمة
عندما يكون هناك عدد كبير من المهام في قائمة الانتظار ليتم تنفيذها في قائمة انتظار مؤشر ترابط العمال ، فإن هذه المهام نفسها قد تستهلك الكثير من موارد النظام وتتسبب في نقص الموارد.
لتلخيص ، عند استخدام تجمعات الخيوط ، يجب اتباع المبادئ التالية:
1. إذا كانت المهمة A تحتاج إلى انتظار نتيجة تنفيذ المهمة B بشكل متزامن أثناء التنفيذ ، فإن المهمة A غير مناسبة لإضافتها إلى قائمة انتظار عمل تجمع الخيوط. إذا كنت بحاجة إلى انتظار مهام أخرى لتنفيذ نتائج مثل المهمة A لإضافتها إلى قائمة الانتظار ، فقد يتسبب ذلك
2. إذا كان من الممكن حظر المهمة وتم حظرها لفترة طويلة ، فيجب ضبط وقت المهلة لتجنب الحظر الدائم لخيط العمال والتسبب في تسرب الخيط. في برنامج الخادم ، عندما ينتظر مؤشر ترابط أن العميل للاتصال أو انتظار البيانات المرسلة من قبل العميل ، فقد يتسبب ذلك في انسداد. يمكنك ضبط الوقت بالطرق التالية:
استدعاء طريقة SetSotimeout لـ ServersOcket لتعيين وقت المهلة للانتظار حتى يتصل العميل.
لكل مأخذ توصيل متصل بالعميل ، اتصل بطريقة SetSotimeout للمقبس لتعيين وقت المهلة في انتظار العميل لإرسال البيانات.
3. فهم خصائص المهمة وتحليل ما إذا كانت المهمة تنفذ العمليات التي غالباً ما تمنع عمليات IO ، أو تنفذ العمليات التي لن تمنع. السابق يحتل وحدة المعالجة المركزية بشكل متقطع ، في حين أن الأخير لديه معدل استخدام أعلى. كم من الوقت يستغرق لإكمال المهمة؟ هل هي مهمة قصيرة الأجل أم مهمة طويلة الأجل؟ بعد ذلك ، قم بتصنيف المهام وفقًا لخصائص المهمة ، ثم إضافة أنواع مختلفة من المهام إلى قائمة انتظار عمل تجمعات الخيوط المختلفة. وبهذه الطريقة ، يمكن تخصيص كل تجمع مؤشر ترابط وتعديله وفقًا لخصائص المهمة.
4. تغيير حجم تجمع الخيوط. يعتمد الحجم الأمثل لمسبح مؤشرات الترابط بشكل أساسي على عدد وحدات المعالجة المركزية المتاحة في النظام وخصائص المهام في قائمة انتظار العمل. إذا كان هناك قائمة انتظار عمل واحدة فقط على نظام مع وحدة المعالجة المركزية N ، وكلها مهام ذات طبيعة حسابية (لا تمنع) ، ثم عندما يكون لتجمع مؤشرات الترابط N أو N+1 ، سيتم الحصول على الحد الأقصى لاستخدام وحدة المعالجة المركزية.
إذا كانت قائمة انتظار العمل تحتوي على مهام تؤدي عمليات IO وغالبًا ما تكون حظرًا ، فاجعل حجم تجمع مؤشرات الترابط يتجاوز عدد وحدات المعالجة المركزية المتاحة ، لأن جميع مؤشرات ترابط العمل لا تعمل طوال الوقت. حدد مهمة نموذجية ثم تقدير نسبة وقت الانتظار إلى الوقت الذي يحتل وحدة المعالجة المركزية بالفعل لأداء عمليات في المشروع الذي يؤدي هذه المهمة. بالنسبة لنظام مع CPUs N ، يجب تعيين مؤشرات الترابط N*(1+WT/ST) تقريبًا لضمان استخدام وحدة المعالجة المركزية بالكامل.
بطبيعة الحال ، فإن استخدام وحدة المعالجة المركزية ليس هو الشيء الوحيد الذي يجب مراعاته في عملية ضبط تجمعات الخيوط. مع زيادة عدد أعمال تجمع مؤشرات الترابط ، ستحدث أيضًا ذاكرة أو قيود الموارد الأخرى ، مثل المقابس ، أو مقابض الملفات المفتوحة أو اتصالات قاعدة البيانات ، وما إلى ذلك. من الضروري أن تكون موارد النظام التي تستهلكها عمليات التراجع المتعددة ضمن نطاق القدرة على التحمل للنظام.
5. تجنب التحميل الزائد للمهمة. يجب أن يحد الخادم من عدد الاتصالات المتزامنة للعملاء بناءً على سعة حمل النظام. عندما يتجاوز اتصال العميل قيمة الحد ، يمكن للخادم رفض الاتصال وإنشاء مطالبات ودية ، أو الحد من طول قائمة الانتظار.
إن العديد من أساليب التنفيذ والأجوبة على تجمعات مؤشرات ترابط Java أعلاه هي المحتوى الذي شاركته معك. آمل أن تتمكن من إعطائك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.