简体   繁体   English

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

[英]Java thread execution limited by count and time

I have list of Processes and i want to execute them like, Ten processes per minute . 我有进程列表,我想像每分钟执行十个进程那样执行它们。

I tried ExecutorService , ThreadPoolExecutor , RateLimiter but none of them can support my case, also i tried RxJava but maybe i cannot figure out how ti implement it correctly. 我尝试了ExecutorServiceThreadPoolExecutorRateLimiter但是它们都不支持我的情况,我也尝试了RxJava但也许我不知道如何正确实现它。


Example

I have list of Runnable with size 100K , each Runnable have this logic: 我有大小为100KRunnable列表,每个Runnable具有以下逻辑:

  • Retrieve data from rest api . rest api检索数据。
  • Do some calculation on data. 对数据进行一些计算。
  • Save the result in database. 将结果保存在数据库中。

So i used ExecutorService with size 10 and make Delay(5 seconds) inside Runnable#run() to manage what i need "Ten processes per minute" , but still, it's not manageable. 因此,我使用大小为10的 ExecutorService并在Runnable#run() 内设置Delay(5秒)来管理我需要的“每分钟十个进程” ,但仍然无法管理。

The main point of this logic to decrease requests on rest api . 该逻辑的要点是减少对rest api请求。


UPDATE 更新

effectively what we're looking for is to have an upper limit (in time and count of operations) rather than evenly distribute the time across operations regardless of their individual throughput. 有效地,我们正在寻找的是有一个上限(时间和操作数),而不是将时间均匀地分配给各个操作,而不管它们的吞吐量如何。

ie if I have a list of 100 ops which will take 0.5 seconds each, and I have a rate limiter than (after distribution) determined that a single operation should take 0.8 seconds I then have a gap of 0.3 second I can use to start a new operation 例如,如果我有一个100个操作的列表,每个操作将花费0.5秒,并且我有一个速率限制器,该速率限制器比(分配后)确定单个操作应花费0.8秒,那么我可以使用0.3秒的间隔来启动一个新操作

I would probably feed my threadPool from a DelayQueue to limit yourself to 10 per minute. 我可能会从DelayQueue喂我的threadPool,以将自己限制为每分钟10个。

See https://stackoverflow.com/a/6306244/823393 for an example of how to feed an executor from a BlockingQueue . 有关如何从BlockingQueue馈给执行程序的示例,请参见https://stackoverflow.com/a/6306244/823393

You mean like this? 你的意思是这样吗? A single executor which spawns a thread which itself spawns 10 threads. 产生线程的单个执行程序本身会产生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));
    }
}

I think you will get the best results using a java.util.Timer and schedule a TimerTask at a fixed rate . 我认为您可以使用java.util.Timer并以固定的速率安排TimerTask来获得最佳结果。

Let's say you have a TimerTask that prints out the date when executed. 假设您有一个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);
    }
}

then create a timer and schedule the tasks. 然后创建一个计时器并安排任务。 Each with a different delay so that they are equally distributed within your preferred time interval. 每个都有不同的延迟,以便它们在您首选的时间间隔内平均分配。

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);
    }
}

and you will see that every 6 seconds a task gets executed. 您会看到每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
....

Keep in mind that a Timer does not run as a daemon thread by default. 请记住,默认情况下, Timer不会作为守护程序线程运行。 If you don't cancel it explicitly on application shutdown it keeps runnig and thus your application will not shutdown. 如果您没有在应用程序关闭时明确取消它,则它将保持运行状态,因此您的应用程序将不会关闭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM