كيفية تنفيذ بسيطة خيوط مع عدد محدد من المواضيع عامل

StackOverflow https://stackoverflow.com/questions/125333

سؤال

أنا أبحث عن أبسط طريقة مباشرة تنفيذ ما يلي:

  • البرنامج الرئيسي instantiates عامل المواضيع للقيام بهذه المهمة.
  • فقط n المهام يمكن أن تكون قيد التشغيل في وقت واحد.
  • عندما n يتم التوصل إلى أي مزيد من العمال وبدأت حتى العد تشغيل المواضيع قطرات أدناه n.
هل كانت مفيدة؟

المحلول

أعتقد أن والمنفذين.newFixedThreadPool يناسب الاحتياجات الخاصة بك.هناك عدد من الطرق المختلفة لاستخدام الناتجة ExecutorService ، اعتمادا على ما إذا كنت تريد النتيجة عاد إلى الموضوع الرئيسي ، أو إذا كانت المهمة هو تماما مكتفية ذاتيا ، وما إذا كان لديك مجموعة من المهام لتنفيذ مقدما ، أو ما إذا كانت المهام في قائمة الانتظار في الرد على بعض الأحداث.

  Collection<YourTask> tasks = new ArrayList<YourTask>();
  YourTask yt1 = new YourTask();
  ...
  tasks.add(yt1);
  ...
  ExecutorService exec = Executors.newFixedThreadPool(5);
  List<Future<YourResultType>> results = exec.invokeAll(tasks);

بدلا من ذلك, إذا كان لديك جديد غير متزامن المهمة لأداء ردا على بعض الأحداث, ربما كنت ترغب فقط في استخدام ExecutorService بسيطة execute(Runnable) الأسلوب.

نصائح أخرى

/* Get an executor service that will run a maximum of 5 threads at a time: */
ExecutorService exec = Executors.newFixedThreadPool(5);
/* For all the 100 tasks to be done altogether... */
for (int i = 0; i < 100; i++) {
    /* ...execute the task to run concurrently as a runnable: */
    exec.execute(new Runnable() {
        public void run() {
            /* do the work to be done in its own thread */
            System.out.println("Running in: " + Thread.currentThread());
        }
    });
}
/* Tell the executor that after these 100 steps above, we will be done: */
exec.shutdown();
try {
    /* The tasks are now running concurrently. We wait until all work is done, 
     * with a timeout of 50 seconds: */
    boolean b = exec.awaitTermination(50, TimeUnit.SECONDS);
    /* If the execution timed out, false is returned: */
    System.out.println("All done: " + b);
} catch (InterruptedException e) { e.printStackTrace(); }

والمنفذين.newFixedThreadPool(الباحث)

Executor executor = Executors.newFixedThreadPool(n);

Runnable runnable = new Runnable() {
 public void run() {
  // do your thing here
 }
}

executor.execute(runnable);

استخدام المنفذ الإطار ؛ وهي newFixedThreadPool(N)

  1. إذا مهمتك الانتظار لن يكون غير المهام كاملة في أقصر فترات زمنية ، يمكنك استخدام Executors.newFixedThreadPool(n);كما يوحي من قبل الخبراء.

    العيب الوحيد في هذا الحل غير محدود انتظار مهمة الحجم.لا نملك السيطرة عليه.كومة ضخمة في انتظار مهمة سوف تحط من أداء التطبيق و قد يسبب نفاد الذاكرة في بعض السيناريوهات.

  2. إذا كنت ترغب في استخدام ExecutorService وتمكين work stealing آلية حيث الخمول المواضيع عامل تقاسم عبء العمل من عامل مشغول المواضيع التي كتبها سرقة المهام في قائمة انتظار العمل.فإنه سيعود ForkJoinPool نوع من منفذ الخدمة.

    الجمهور ثابت ExecutorService newWorkStealingPool(الباحث التوازي)

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

  3. أنا أفضل ThreadPoolExecutor بسبب المرونة في واجهات برمجة التطبيقات إلى السيطرة على العديد من paratmeters الذي يتحكم في تدفق تنفيذ المهمة.

    ThreadPoolExecutor(int corePoolSize, 
                           int maximumPoolSize, 
                           long keepAliveTime, 
                           TimeUnit unit, 
                           BlockingQueue<Runnable> workQueue, 
                           ThreadFactory threadFactory,
                           RejectedExecutionHandler handler)
    

في حالة تعيين كل من corePoolSize and maximumPoolSize as N.هنا يمكنك التحكم في انتظار مهمة الحجم ، وتحديد المخصصة الخاصة بك موضوع مصنع رفض معالج السياسة.

إلقاء نظرة على ذات SE السؤال للتحكم في حجم تجمع حيوي:

ديناميكية تجمع مؤشرات الترابط

إذا كنت ترغب في لفة الخاص بك:

private static final int MAX_WORKERS = n;
private List<Worker> workers = new ArrayList<Worker>(MAX_WORKERS);

private boolean roomLeft() {
    synchronized (workers) {
        return (workers.size() < MAX_WORKERS);
    }
}

private void addWorker() {
    synchronized (workers) {
        workers.add(new Worker(this));
    }
}

public void removeWorker(Worker worker) {
    synchronized (workers) {
        workers.remove(worker);
    }
}

public Example() {
    while (true) {
        if (roomLeft()) {
            addWorker();
        } 
    }
}

حيث عامل هو الدرجة التي يمتد الموضوع.كل عامل سوف نسمي هذه الفئة removeWorker طريقة تمرير نفسها في كمعلمة ، عندما ينتهي به الأمر شيء.

وقال مع ذلك, المنفذ الإطار تبدو أفضل كثيرا.

تحرير:أحد أن يفسر لماذا هذا السوء ، بدلا من مجرد downmodding ؟

مثل الآخرين هنا قد ذكرت ، وأفضل رهان هو جعل تجمع مؤشرات الترابط مع منفذي الدرجة:

ومع ذلك ، إذا كنت ترغب في لفة الخاص بك, هذا الرمز يجب أن تعطيك فكرة عن كيفية المضي قدما.في الأساس, فقط إضافة كل جديد الخيط إلى الخيط الفريق وتأكد من أن لديك أبدا أكثر من ن النشطة المواضيع في المجموعة:

Task[] tasks = getTasks(); // array of tasks to complete
ThreadGroup group = new ThreadGroup();
int i=0;
while( i<tasks.length || group.activeCount()>0 ) {
    if( group.activeCount()<N && i<tasks.length ) {
        new TaskThread(group, tasks[i]).start();
        i++;
    } else {
        Thread.sleep(100);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top