Выполнение потока Java ограничено количеством и временем - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть список Процессов , и я хочу выполнить их как Десять процессов в минуту .

Я пытался ExecutorService, ThreadPoolExecutor, RateLimiter но ни один из них не может поддержать мой случай, также я попытался RxJava, но, возможно, я не могу понять, как правильно его реализовать.


Пример

У меня есть список Runnable с размером 100K , каждый Runnable имеет следующую логику:

  • Извлечение данных из rest api.
  • Выполните некоторые вычисления на данных.
  • Сохраните результат в базе данных.

Поэтому я использовал ExecutorService с размером 10 и сделал Задержка (5 секунд) внутри Runnable#run() чтобы управлять тем, что мне нужно «Десять процессов в минуту» , но все же, это не поддается управлению.

Суть этой логики - уменьшить количество запросов на rest api.


ОБНОВЛЕНИЕ

Эффективно то, что мы ищем, это иметь верхний предел (по времени и количеству операций), а не равномерно распределять время по операциям.ss их индивидуальной пропускной способности.

т.е. если у меня есть список из 100 операций, который займет 0,5 секунды каждый, и у меня есть ограничитель скорости, который (после распределения) определил, что одна операция должна занять 0,8 секунды, тогдаесть интервал 0,3 секунды, который я могу использовать, чтобы начать новую операцию

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Вы имеете в виду, как это?Один исполнитель, который порождает поток, который сам порождает 10 потоков.

private static final int numProcesses = 10;
private static final ExecutorService executorService = Executors.newFixedThreadPool(numProcesses);

public static void main(String[] args)
{
    final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleAtFixedRate(Test::spawnTenThreads, 0, 5, TimeUnit.SECONDS);
}

private static void spawnTenThreads()
{
    for (int i = 0; i < numProcesses; ++i)
    {
        final int iteration = i;
        executorService.submit(() -> System.out.println(iteration));
    }
}
0 голосов
/ 20 февраля 2019

Я думаю, вы получите лучшие результаты, используя java.util.Timer и запланируете TimerTask по фиксированной ставке .

Допустим, у вас есть TimerTask, который печатает дату при выполнении.

public class PrintTimeAndIdTask extends TimerTask {

    private int id;

    public PrintTimeAndIdTask(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println(new Date() + " : " + id);
    }
}

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

public static void main(String[] args) {
    Timer timer = new Timer();

    int taskCount = 10;
    int timeIntervalMs = 60000;
    int delayBetweenTasks = timeIntervalMs / taskCount;


    for (int i = 0; i < taskCount; i++) {
        TimerTask timerTask = new PrintTimeAndIdTask(taskCount);

        int taskDelay = (long) taskCount * delayBetweenTasks;

        timer.scheduleAtFixedRate(timerTask, taskDelay, timeIntervalMs);
    }
}

, и вы увидите, что каждые 6 секунд выполняется задание.

Wed Feb 20 17:17:37 CET 2019 : 0
Wed Feb 20 17:17:43 CET 2019 : 1
Wed Feb 20 17:17:49 CET 2019 : 2
Wed Feb 20 17:17:55 CET 2019 : 3
Wed Feb 20 17:18:01 CET 2019 : 4
Wed Feb 20 17:18:07 CET 2019 : 5
Wed Feb 20 17:18:13 CET 2019 : 6
Wed Feb 20 17:18:19 CET 2019 : 7
Wed Feb 20 17:18:25 CET 2019 : 8
Wed Feb 20 17:18:31 CET 2019 : 9
Wed Feb 20 17:18:37 CET 2019 : 0
Wed Feb 20 17:18:43 CET 2019 : 1
Wed Feb 20 17:18:49 CET 2019 : 2
Wed Feb 20 17:18:55 CET 2019 : 3
....

Сохранить впомните, что Timer по умолчанию не запускается как поток демона.Если вы не отмените его явным образом при завершении работы приложения, оно продолжит работу и, следовательно, ваше приложение не будет закрыто.

0 голосов
/ 20 февраля 2019

Я бы, вероятно, передал свой threadPool из DelayQueue , чтобы ограничить себя 10 в минуту.

См. https://stackoverflow.com/a/6306244/823393 для примера того, как накормить исполнителя изBlockingQueue.

...