java - Java中的一种负载平衡线程池

标签 java multithreading threadpool pool

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

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

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

我的第一个想法: 有 12 个线程,最多允许三个作业并行。 但是:这意味着,当只有 1 个工作时,cou 尚未完全化。

我正在寻找一种解决方案,以便在没有其他作业时为第一个作业提供完整的 CPU 能力。但是当另一个作业需要在另一个作业运行时启动时,我希望将 CPU 功率分配给两个作业。当出现第三个或第四个作业时,我希望将 CPU 能力公平地分配给所有四个作业。

我很感激你的回答...

提前致谢

最佳答案

一种可能是使用带有不同类型任务队列的标准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;
    }
  }
}

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

taskRunner.runTasks(jobTask1, jobTask2, jobTask3);

它会将任务排队,使它们与队列中的任何现有任务(如果有)很好地交错。假设您有一个作业在排队,其任务的优先级编号为 j1t1=3,j1t2=103,且 j1t3=203。在没有其他作业的情况下,这些任务会以最快的速度一个接一个地执行。但是,如果您提交另一个包含三个任务的作业,它们将被分配优先级编号 j2t1=4, j2t 2=104 和 j2t3=204,这意味着队列现在看起来像

j1t1, j2t1, j1 t2, j2t2

但这并不完美,因为如果所有线程当前都在工作(处理来自作业 1 的任务),那么作业 2 的第一个任务将无法启动,直到作业 1 的其中一个任务完成(除非有一些外部方式你检测到这一点并中断并重新排队一些作业 1 的任务)。使事情变得更公平的最简单方法是将运行时间较长的任务分解为更小的部分,并将它们作为单独的任务排队——你需要达到这样的程度,即每个单独的工作涉及的任务比池中的线程多,这样一些任务将始终在队列中开始而不是直接分配给线程(如果有空闲线程然后 exec.execute() 将任务直接传递给线程而不经过完全排队)。

关于java - Java中的一种负载平衡线程池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14415343/

相关文章:

java - Android 设备上的 PowerManager.WakeLock

java - Gradle : Unable to initialize POM pom-default. xml:无法验证 POM

c++ - C++ 中的错误共享

c++ - I/O 完成端口与 QueueUserApc?

windows - Qt 多头控制台应用程序在退出时挂起(使用 ctrl-c)

JAVA - 扩展与接口(interface) - 策略设计模式

java - 如何确定java应用程序中的主类?

multithreading - 为线程设置亲和性掩码有真正的性能提升吗?

c# - 调用 Task.Result 时出现 ThreadAbortException

c# - 限制每个类的线程