java中的负载均衡线程池

Chr*_*ohr 8 java multithreading pool threadpool

我正在寻找一个负载均衡的线程池到目前为止没有成功.(不确定负载平衡是否是正确的措辞).让我解释一下我试图实现的目标.

第1部分:我有乔布斯,有8到10个单一任务.在6核CPU上,让8个线程并行处理这个任务,这似乎可以提供最佳的性能.当一个任务准备就绪时,另一个任务就可以开始.完成所有十项任务后,完成整个工作.通常,工作在30到60秒内完成.

第二部分:有时,不幸的是,这项工作需要两个多小时.由于必须计算的数据量,这是正确的.坏的是,在job1运行时没有其他工作可以启动(假设所有线程具有相同的持续时间),因为它正在使用所有线程.

我的第一个想法:拥有12个线程,并行允许最多三个作业.但是:这意味着,当只有一份工作时,这项工作就没有完全实现.

我正在寻找一种解决方案,在没有其他工作的情况下为作业1提供全部CPU能力.但是当另一个工作需要在另一个工作时启动时,我希望将CPU功率分配给这两个工作.当第三或第四个工作出现时,我希望cpu电源公平地分配给所有四个工作.

我赞成你的答案......

提前致谢

Ian*_*rts 6

一种可能性是使用ThreadPoolExecutor具有不同类型的任务队列的标准

public class TaskRunner {
  private static class PriorityRunnable implements Runnable,
            Comparable<PriorityRunnable> {
    private Runnable theRunnable;
    private int priority = 0;
    public PriorityRunnable(Runnable r, int priority) {
      this.theRunnable = r;
      this.priority = priority;
    }

    public int getPriority() {
      return priority;
    }

    public void run() {
      theRunnable.run();
    }

    public int compareTo(PriorityRunnable that) {
      return this.priority - that.priority;
    }
  }

  private BlockingQueue<Runnable> taskQueue = new PriorityBlockingQueue<Runnable>();

  private ThreadPoolExecutor exec = new ThreadPoolExecutor(8, 8, 0L,
            TimeUnit.MILLISECONDS, taskQueue);

  public void runTasks(Runnable... tasks) {
    int priority = 0;
    Runnable nextTask = taskQueue.peek();
    if(nextTask instanceof PriorityRunnable) {
      priority = ((PriorityRunnable)nextTask).getPriority() + 1;
    }
    for(Runnable t : tasks) {
      exec.execute(new PriorityRunnable(t, priority));
      priority += 100;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的想法是,当你有一份新工作时,你会打电话

taskRunner.runTasks(jobTask1, jobTask2, jobTask3);
Run Code Online (Sandbox Code Playgroud)

并且它将以这样的方式排队任务:它们与队列中的任何现有任务(如果有的话)很好地交错.假设您有一个排队的作业,其任务具有优先级数j 1 t 1 = 3,j 1 t 2 = 103和j 1 t 3 = 203.在没有其他工作的情况下,这些任务将尽快一个接一个地执行.但是如果你提交另一个有三个任务的作业,这些将被分配优先级数j 2 t 1 = 4,j 2 t 2 = 104和j 2 t 3 = 204,这意味着队列现在看起来像

j 1 t 1,j 2 t 1,j 1 t 2,j 2 t 2

然而,这并不完美,因为如果所有线程当前都在工作(来自作业1的任务),则作业2的第一个任务无法启动,直到其中一个作业1任务完成(除非有一些外部方法供您检测这会中断并重新排队一些作业1的任务).使事情变得更公平的最简单方法是将较长时间运行的任务分解为较小的段并将它们排列为单独的任务 - 您需要达到每个单独的工作涉及的任务多于池中的线程,因此,某些任务将始终在队列中启动,而不是直接分配给线程(如果有空闲线程,则将exec.execute()任务直接传递给线程而根本不通过队列).