2012-04-19 4 views
0

Хорошо, я объясню, что я прошу, подав пример.Контролируемый вызов Runnables на потоках

позволяет сказать, что им пытаются реализовать параллельный алгоритм слияния при Дано:

дб является массивом, где дб [я] является ArrayList объектов.

j - его размер. Слияние (дБ, CMP, I, J) является работоспособным, которая объединяет дБ [J]вдБ [I].

cmp - соответствующий компаратор.

Это то, что я во-первых Done:

ExecutorService e = Executors.newFixedThreadPool(3); 
    while (j>0) 
     for (i=0;i<j;i++,j--) 
      e.execute(new Merger<E>(db,cmp,i,j)); 

но некоторые слияния были начаты в то время как предыдущие слияния, которые необходимо завершить первый еще не были окончены. (не говоря уже о том, что бегущая нить закончила цикл до того, как слияние было закончено ...), и это заставило мою программу выпустить Exeception.

Это то, что я могу делать, но хочу сделать, и поэтому нужна ваша помощь:

ExecutorService e = Executors.newFixedThreadPool(3); 
    while (j>0) { 
     for (i=0;i<j;i++,j--) 
      e.execute(new Merger<E>(db,cmp,i,j)); 
     wait for e to announce that all runnables have finished running; 
    } 

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

(основно я могу осуществить свою собственную версию FixedThreadPool, чтобы сделать его heppen, но я скорее не)

ответ

1

Вам нужно «startAndRendezvous» работоспособным, что вопросы слияния и ждут их завершения. Обычно это делается путем создания набора заданий слияния, заданных с обратным вызовом, указывающим на CountDownlatch в startAndRendezvous или, более гибко, передать startAndRendezvous в качестве параметра конструктора в исполняемые файлы слияния.

В последней версии Java есть ForkJoinPool. Посмотрите на класс - он сохраняет, имея явный обратный отсчет.

+0

нравится как?ваш ответ слишком абстрактен. –

-1

простой способ, который должен работать, чтобы определить статический счетчик Присоединения:

public class Merger<E> ... { 
    public static int runningCount=0; 
    public Merger(...){ 
    runningCount++; 
    } 
    public void run(){ 
    ... 
    runnningCount--; 
    } 
} 

Тогда:

ExecutorService e = Executors.newFixedThreadPool(3);  
while (j>0) { 
    for (i=0;i<j;i++,j--) 
     e.execute(new Merger<E>(db,cmp,i,j)); 
    while(Merger.runningCount>0) 
     Thread.sleep(10); 
} 
+1

runningCount должен быть AtomicInteger или это не сработает. И прямая блокировка редко является лучшей идеей - даже если в цикле есть Thread.sleep. – yshavit

+0

@yshavit = да, или заблокирован. Цикл sleep() просто плох - например, Wait/Notify. Кроме того, теперь есть класс ForkJoinPool. –

+0

благодарим вас за отзыв, я этого не сделал. Решение @Philipp Reichart выглядит лучше –

2

Вы можете быть ищете CountDownLatch:

  • Определения количество потоков, которые вам нужно подождать, и создать CountDownLatch с этим номером
  • Передайте защелку всем рабочим потокам при их создании и попросите их позвонить countDown() после их завершения.
  • После цикла, который завершает рабочие потоки, await(), что обратный отсчет достигает нуля.
Смежные вопросы