Java - несколько Runnables на поток - PullRequest
0 голосов
/ 30 июня 2011

Я получил фиксированное количество потоков.Я хочу, чтобы каждый поток выполнялся три Runnable с, один за другим.Вот несколько псевдокодов для объяснения:

Thread[] threads = new Thread[4];

for (int i = 0; i < threads.length; i++) {
    // Set the first tasks.
    threads[i] = new Thread(new FirstRunnable());
    threads[i].start();
}

for (int i = 0; i < threads.length; i++)
    threads[i].join(); // wait until the first tasks are done

for (int i = 0; i < threads.length; i++) {
    // Set the second task.
    threads[i].setRunnable(new SecondRunnable());
    threads[i].start();
}

for (int i = 0; i < threads.length; i++)
    threads[i].join(); // wait until the second tasks are done

...

Использование ThreadPool звучит излишне, особенно учитывая, что я стремлюсь к производительности, производительности и производительности.Какой лучший способ реализовать это в Java?

Ответы [ 5 ]

4 голосов
/ 30 июня 2011

Всякий раз, когда вы видите new Thread(...).start(), используйте Executors рамки.В частности, используйте Executors.newFixedThreadPool(...).

1 голос
/ 30 июня 2011

Похоже, хорошее применение для newFixedThreadPool из Executors class.

Так что ваш код будет выглядеть примерно так:

ExecutorService es = Executors.newFixedThreadPool(4);
List<Future> futures = new ArrayList<Future>();
for (int x = 0; x < 4; x ++) {
    futures.add(es.submit(new FirstRunnable()));
}
while (futures.size() > 0) {
   futures.remove(0).get();
}
for (int x = 0; x < 4; x ++) {
    futures.add(es.submit(new SecondRunnable()));
}

while (futures.size() > 0) {
   futures.remove(0).get();
}

Конечно, вы можетевероятно, легко изменить код выше, чтобы удалить дублирование кода.

1 голос
/ 30 июня 2011

Вы можете использовать CyclicBarrier и "CombinedRunnable", как показано ниже. Барьер позволяет всем потокам ждать завершения друг друга, прежде чем перейти к следующему выполнению.

CyclicBarrier barrier = new CyclicBarrier(4);
Runnable r = new CombinedRunnable(barrier, new FirstRunnable(), new SecondRunnable());
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
    threads[i] = new Thread(r);
    threads[i].start();
}

Класс CombinedRunnable:

public class CombinedRunnable implements Runnable{

    private final CyclicBarrier barrier;
    private final Runnable[] runnables;

    public CombinedRunnable(CyclicBarrier barrier, Runnable... runnables){
        this.barrier = barrier;
        this.runnables = runnables;
    }

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        for(Runnable r: runnables){
            r.run();
            try {
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
0 голосов
/ 30 июня 2011

Идиоматический способ достижения этого - использование Executor в сочетании с CompletionService.Это позволяет сопоставить многие единицы работы с пулом потоков фиксированного размера, а также предоставляет элегантный механизм блокировки до завершения всей работы.

Обратите внимание, что ваше беспокойство по поводу того, как использование пула потоков может повлиять на эффективность,на самом деле это не проблема: основные накладные расходы связаны с созданием отдельных потоков, которые вы все равно выполняете;дополнительные затраты на создание объекта при создании пула будут незначительными.

// Create fixed thread pool and wrap in a CompletionService to allow for easy access to completed tasks.
// We don't have an explicit result for each Runnable so parameterise the service on Void.
CompletionService<Void> cs = new ExecutorCompletionService<Void>(Executors.newFixedThreadPool(3));

// Create units of work for submission to completion service.
Runnable[] runnables = ...

// Submit runnables.  Note that we don't care about the result so pass in null.
for (Runnable r : runnables) {
  cs.submit(r, null);
}

// Take each *completed* result in turn, blocking until a completed result becomes available.
for (int i=0; i<runnables.length; ++i) {
  Future<Void> completed = cs.take();
}
0 голосов
/ 30 июня 2011

Executor Framework - для вас.
Вот псевдокод:
1. Создайте службу исполнителя

Executors type1Runnables = Executors.newFixedThreadPool(4);
Executors type2Runnables = Executors.newFixedThreadPool(4);

и т.1008 *

3.Вызовите исполнителей

type1Runnables.invokeAll();
type2Runnables.invokeAll();

Чтобы сделать его более универсальным, вы, возможно, могли бы написать свой собственный executorservicefactory, который принимает различные выполняемые типы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...