Java线程执行受计数和时间限制

时间:2019-02-20 14:57:20

标签: java multithreading threadpool

我有个进程的列表,我想像每分钟十个进程那样执行它们。

我尝试了ExecutorServiceThreadPoolExecutorRateLimiter,但是他们都不支持我的情况,我也尝试了RxJava,但也许我无法弄清楚如何正确实施


示例

我有一个大小为 100K Runnable列表,每个Runnable都具有以下逻辑:

  • rest api检索数据。
  • 对数据进行一些计算。
  • 将结果保存到数据库中。

所以我用了{strong> 10 的ExecutorService,并在Runnable#run()内设置了 Delay(5秒)来管理我需要的”每分钟十个进程”。,但仍然无法管理。

减少rest api上的请求的逻辑的要点。


更新

实际上,我们正在寻找的是有一个上限(时间和操作数),而不是将时间平均分配到各个操作中,而不管它们的吞吐量如何。

即如果我有一个100个操作的列表,每个操作将花费0.5秒,并且我有一个速率限制器,该速率限制器比(分配后)确定单个操作应花费0.8秒,那么我可以使用0.3秒的间隔来启动一个新操作操作

3 个答案:

答案 0 :(得分:0)

我可能会从DelayQueue喂我的threadPool,将自己限制为每分钟10个。

有关如何从BlockingQueue馈给执行者的示例,请参见https://stackoverflow.com/a/6306244/823393

答案 1 :(得分:0)

您的意思是这样吗?单个执行程序产生一个线程,该线程本身产生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));
    }
}

答案 2 :(得分:0)

我认为您将使用java.util.Timer获得最佳效果,并在TimerTask安排fixed rate

假设您有一个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不会作为守护程序线程运行。如果您没有在应用程序关闭时明确取消它,则它将保持运行状态,因此您的应用程序将不会关闭。