2016-10-26 2 views
0

У меня есть приложение для обработки текста на Java, которое считывает фрагмент файла куском (~ 100000 строк) и обрабатывает каждый фрагмент в отдельном потоке.Производитель/потребитель в Java: поддержание баланса

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

Я хотел бы программу вести себя таким образом:

  • читать 16 ломти и представить их на 8 runnables;
  • если количество необработанных кусков падает ниже 12, читайте еще 4 куска текста.

Это приведет к тому, что Runnables будет занят, но в то же время сохранит память для обработки (вместо хранения кусков).

Как это сделать на Java? Написанная в preudocode Я хочу это:

loop { 

    chunk = readChunkOfData(); 

    counter.inc();  

    processAsync(chunk); 

    if (counter.isBiggerThan(16)) { 
    counter.sleepWhileCounterIsBiggerThan(12); 
    } 
} 

... 

worker { 
    // do the job 

    counter.dec(); 
} 
+3

Просто используйте ограниченные очереди, и они автоматически решат это для вас. –

ответ

1

Как отметил Марко Топольник, используя ограниченные (блокирование) queues может решить вашу проблему элегантно.

Вам не нужен счетчик, так как очередь знает свои пределы, и ваш псевдокод бы закончить тем, что что-то вроде следующего

loop { 
    chunk = readChunkOfData(); 
    queue.put(chunk); 
} 

worker { 
    chunk = queue.take(); 
    process(chunk); 
} 

Это предполагает, что очереди, например new ArrayBlockingQueue(16); и разделяют все работников. Вы также можете использовать drainTo(Collection<? super E> c, int maxElements) в рабочих, чтобы одновременно брать несколько кусков, в качестве дополнительного рабочего буфера на стороне рабочего, но это, вероятно, не будет иметь большого значения.