Как вы устанавливаете 2 потоковых пула, которые работают рядом друг с другом? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть вопрос о пуле потоков.

Вот такая у меня ситуация: Где-то из бэкэндсервиса мы получаем список файлов pdf.
Первоначально эти страницы PDF необходимо преобразовать в.bmp файлы.
После этого преобразования необходимо напечатать эти bmp.

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

Решение, которое я задумал, заключалось в создании 2 потоков ThreadPools: один для преобразования и один для печати. ​​

Это были бы мои Threadpools:

ExecutorService convertPool = Executors.newFixedThreadPool(10);

ExecutorService printPool = Executors.newSingleThreadExecutor();

A convertPool с 10 потоками для преобразования страниц PDF в BMP.
Когда это будет сделано, созданные BMP будут отправлены на printPool,Это одна нить, потому что всегда может быть только одна печать.

Но теперь возникает мой вопрос:
поэтому convertPool выполнил свою работу с первым pdf и отправил все будущие задачи наPrintPool для печати. ​​
Но когда printPool занят, я хочу, чтобы convertPool начинался уже со 2-го pdf.Таким образом, когда PrintPool завершит работу с печатью bmp из первого файла pdf, он может немедленно начать работу с печатью bmp второго файла pdf, поскольку они уже созданы.

Но как я могу это сделать?настроить этот механизм?Может ли кто-нибудь помочь мне с этим?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

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

class Conversion implements Runnable {
    Consumer<Conversion> onCompletion;

    Conversion(Consumer<Conversion> onCompletion) {
        this.onCompletion = onCompletion;
    }

    @Override
    public void run() {
        // ... conversion code. You could Thread.sleep()
        // here to simulate the conversion work taking up
        // some time.

        // (now we're done converting)
        onCompletion.accept(this);
    }
}

class Print implements Runnable {
    Print(Conversion c) {
        // ...
    }

    // ...run() method, etc.
}

// Example of submitting a conversion task to the executor
convertPool.submit(new Conversion(c -> printPool.submit(new Print(c))));
0 голосов
/ 28 ноября 2018
  • вы можете использовать одного и того же исполнителя для выполнения работ для печати задания.
  • в этом исполняемом файле вы можете ссылаться на Список фьючерсов, созданных в результате выполнения вызовов, которые фактически обрабатывают ваши PDF-файлы.
  • список, конечно, будет иметь глобальную ссылку.
  • теперь вы можете использовать семафоры с ограниченными разрешениями, скажем, (10), и, в то время как любой вызываемый
    завершает выполнение, он может высвободить разрешение, которое исполняемый объект
    попытается получить заранее и, таким образом, остатьсяв заблокированном состоянии, так как ни один из них не будет доступен.

    ПРИМЕЧАНИЕ. При каждой обработке PDF Callable получает разрешение в начале своего выполнения.

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

  • единицы, все тэки завершили выполнениеили когда снова будет доступно 10 разрешений, вы можете прекратить выполнение исполнителя, выполнив shutdownNow(), завершив тем самым выполнение.

Надеюсь, это поможет!

...