从后台线程更均匀地传播负载

时间:2014-08-30 16:00:12

标签: java multithreading scheduledexecutorservice

我有一个后台线程,每5分钟运行一次。我正在使用ScheduledExecutorService。每隔五分钟,我就会打电话给我的一个服务并解析从该服务返回的响应。

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, 0, 5L, TimeUnit.MINUTES);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}

现在上面的代码在1000台机器上运行,它们都是同时启动的,这意味着它将同时为我的服务每5分钟拨打1000个电话。我试图在5分钟的窗口内更均匀地分散负载。用上述代码可以做到这一点吗?

我只是试图在5分钟的窗口上更均匀地将负载分散到我的服务上,这样它就不会在同一时间点击我的服务,这会在所有系统同时启动时增加负载。

我想出了下面的代码,试图在五分钟的窗口内更均匀地分散负载:

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, (int)(Math.random()*5*60), 5*60L, TimeUnit.SECONDS);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}

这是否是在5分钟窗口内均匀分散负载的正确方法。

1 个答案:

答案 0 :(得分:1)

这在某种程度上会有所帮助,但是在第一次变异之后,时间表仍然是固定的。另一种分散负载的方法是使用"schedule with fixed delay"并在每次执行中放置一个短暂的随机暂停(例如Thread.sleep(Math.random()*5000L)之前的callService()。随着时间的推移会导致更多的变化。

另外,为了测试可变性,您可以创建一个简单的测试程序,打印出当前时间(以毫秒为单位),而不是调用实际服务。使用不同的算法运行您的测试程序一小时并绘制结果图表。选择能让你获得最佳传播的版本。