سؤال

أحاول استخدام threadpoolexecutor لتحديد موعد المهام ، ولكن مواجهة بعض المشكلات مع سياساتها. هذا سلوكه المعلن:

  1. في حالة تشغيل مؤشرات الترابط CorePoolsize أقل من CorePoolsize ، يفضل المنفذ دائمًا إضافة مؤشر ترابط جديد بدلاً من طابور.
  2. في حالة تشغيل CorePoolSize أو المزيد من المواضيع ، يفضل المنفذ دائمًا طابور طلب بدلاً من إضافة مؤشر ترابط جديد.
  3. إذا لم يكن من الممكن قائمة الطلب ، يتم إنشاء مؤشر ترابط جديد ما لم يتجاوز هذا Maximumpoolsize ، وفي هذه الحالة ، سيتم رفض المهمة.

السلوك الذي أريده هو:

  1. نفسه على النحو الوارد أعلاه
  2. إذا كان أكثر من CorePoolsize ولكن أقل من مؤشرات ترابط MaximumpoolSize قيد التشغيل ، فحسب إضافة مؤشر ترابط جديد عبر قائمة الانتظار ، واستخدام مؤشر ترابط الخمول فوق إضافة مؤشر ترابط جديد.
  3. نفسه على النحو الوارد أعلاه

في الأساس لا أريد رفض أي مهام ؛ أريدهم أن يتم طابورهم في قائمة انتظار غير محدودة. لكني أريد أن أحصل على خيوط Maximumpoolsize. إذا استخدمت قائمة انتظار غير محدودة ، فهي لا تنشئ مؤشرات ترابط بعد أن تضرب الحشائش. إذا استخدمت قائمة انتظار محددة ، فإنه يرفض المهام. هل هناك أي طريقة للتغلب على هذه؟

ما أفكر فيه الآن هو تشغيل threadpoolexecutor على متزامن ، ولكن لا تتغذى على مهامها مباشرة - بدلاً من ذلك إطعامها إلى LinkedBlocking غير محدودة. ثم يتغذى مؤشر ترابط آخر من LinkedBlockingQueue إلى المنفذ ، وإذا تم رفض أحدهم ، فإنه يحاول ببساطة مرة أخرى حتى لا يتم رفضه. هذا يبدو وكأنه ألم وقليل من الاختراق ، على الرغم من - هل هناك طريقة أنظف للقيام بذلك؟

هل كانت مفيدة؟

المحلول

حالة الاستخدام الخاصة بك شائعة ، شرعية تمامًا ، وللأسف أكثر صعوبة مما يتوقعه المرء. للحصول على معلومات خلفية يمكنك قراءتها هذه المناقشة وابحث عن مؤشر إلى حل (مذكور أيضًا في الخيط) هنا. حل شاي يعمل بشكل جيد.

عمومًا سأكون حذرًا بعض الشيء من قوائم الانتظار غير المحدودة ؛ من الأفضل عادة أن يكون لديك التحكم الصريح في التدفق الواردة التي تتحلل بأمان وتنظم نسبة العمل الحالي/المتبقي إلى عدم التغلب على المنتج أو المستهلك.

نصائح أخرى

ربما ليس من الضروري إدارة تجمع الخيوط الجزئي كما هو مطلوب.

سيقوم تجمع الخيوط المخبأة بإعادة استخدام مؤشرات الترابط الخمول مع السماح أيضًا بخيوط متزامنة محتملة غير محتملة. هذا بالطبع يمكن أن يؤدي إلى هارب الأداء مهين من تبديل السياق النفقات العامة خلال فترات الانفجار.

Executors.newCachedThreadPool();

يتمثل الخيار الأفضل في وضع حد على إجمالي عدد مؤشرات الترابط مع التخلص من فكرة ضمان استخدام مؤشرات الترابط الخاملة أولاً. ستكون تغييرات التكوين:

corePoolSize = maximumPoolSize = N;
allowCoreThreadTimeOut(true);
setKeepAliveTime(aReasonableTimeDuration, TimeUnit.SECONDS);

التفكير في هذا السيناريو ، إذا كان لدى المنفذ أقل من corePoolSize المواضيع ، مما يجب ألا يكون مشغولاً للغاية. إذا لم يكن النظام مشغولاً للغاية ، فهناك ضرر ضئيل في تدوير موضوع جديد. القيام بذلك سيؤدي ThreadPoolExecutor لإنشاء عامل جديد دائمًا إذا كان تحت الحد الأقصى لعدد العمال المسموح به. فقط عندما يكون الحد الأقصى لعدد العمال "يركض" العمال ينتظرون مهام المهام. إذا كان العامل ينتظر aReasonableTimeDuration بدون مهمة ، ثم يُسمح للإنهاء. باستخدام حدود معقولة لحجم المسبح (بعد كل شيء ، لا يوجد سوى العديد من وحدات المعالجة المركزية) ومهلة كبيرة بشكل معقول (لمنع المواضيع من الانتهاء دون داع) ، من المحتمل أن تُرى الفوائد المطلوبة.

الخيار النهائي هو الاختراق. أساسا ، و ThreadPoolExecutor يستخدم داخليا BlockingQueue.offer لتحديد ما إذا كانت قائمة الانتظار لديها القدرة. تطبيق مخصص لـ BlockingQueue يمكن دائمًا رفض offer محاولة. عندما ThreadPoolExecutor فشل ل offer مهمة في قائمة الانتظار ، ستحاول إنشاء عامل جديد. إذا لم يكن من الممكن إنشاء عامل جديد ، أ RejectedExecutionHandler سوف يسمى. في تلك المرحلة ، العادة RejectedExecutionHandler يمكن أن يفرض put في العادة BlockingQueue.

/** Hackish BlockingQueue Implementation tightly coupled to ThreadPoolexecutor implementation details. */
class ThreadPoolHackyBlockingQueue<T> implements BlockingQueue<T>, RejectedExecutionHandler {
    BlockingQueue<T> delegate;

    public boolean offer(T item) {
        return false;
    }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        delegate.put(r);
    }

    //.... delegate methods
}

فقط ضبط corePoolsize = maximumPoolSize واستخدام قائمة انتظار غير محدودة؟

في قائمة النقاط الخاصة بك ، يستبعد 1 2 ، منذ ذلك الحين corePoolSize سيكون دائما أقل أو متساوية من maximumPoolSize.

تعديل

لا يزال هناك شيء غير متوافق بين ما تريد وما الذي سيقدمه لك TPE.

إذا كان لديك قائمة انتظار غير محدودة ، maximumPoolSize يتم تجاهل ذلك ، كما لاحظت ، لا أكثر من corePoolSize سيتم إنشاء المواضيع واستخدامها.

لذلك ، مرة أخرى ، إذا كنت تأخذ corePoolsize = maximumPoolSize مع قائمة انتظار غير محدودة ، لديك ما تريد ، لا؟

هل تبحث عن شيء يشبه تجمع الخيوط المخزنة مؤقتًا؟

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/executors.html#newcachedthreadpool ()

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top