Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的一种负载平衡线程池_Java_Multithreading_Threadpool_Pool - Fatal编程技术网

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

java中的一种负载平衡线程池,java,multithreading,threadpool,pool,Java,Multithreading,Threadpool,Pool,我正在寻找一个负载平衡的线程池,到目前为止还没有成功。(不确定负载平衡是否是正确的措辞)。 让我解释一下我试图实现的目标 第1部分: 我有工作,有8到10个单项任务。在6核CPU上,我让8个线程并行处理这些任务,这似乎提供了最佳性能。当一项任务准备就绪时,另一项任务就可以开始了。一旦这十项任务全部完成,整个工作就完成了。通常一项工作在30到60秒内完成 第二部分: 不幸的是,有时这项工作需要两个多小时。这是正确的,因为需要计算的数据量很大。 糟糕的是,当job1运行时(假设所有线程的持续时间相同

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

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

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

我的第一个想法是: 具有12个线程,最多允许并行执行三个作业。 但是:这意味着,当只有一个作业时,cou还没有完全解除

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

我很感激你的回答


我想先谢谢你,因为你的机器是6核CPU。每个作业线程最好有6个工作线程。因此,每当一个线程获得一个新作业时,它就会启动多达六个并行工作线程来处理单个作业。这将确保在一次只有一个作业时消耗全部cpu电源

另外,请看一下Java7中的Fork和Join概念





还了解newcachedthreadpool()


一种可能是将标准的
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;
    }
  }
}
它将以这样一种方式对任务进行排队:它们与队列中的任何现有任务(如果有的话)巧妙地交织在一起。假设有一个作业排队,其任务的优先级为j1t1=3、j1t2=103和j1t3=203。在没有其他作业的情况下,这些任务将尽快一个接一个地执行。但是,如果您提交了另一个包含三个任务的作业,这些任务将被分配优先级号j2t1=4、j2t2=104和j2t3=204,这意味着队列现在看起来像

j1t1、j2t1、j1t2、j2t2等


但是,这并不完美,因为如果所有线程当前都在工作(在作业1的任务上),那么作业2的第一个任务在作业1的一个任务完成之前无法启动(除非有某种外部方法让您检测到这一点,并中断作业1的一些任务并重新排队)。让事情变得更公平的最简单方法是将运行时间较长的任务分解为较小的部分,并将它们作为单独的任务进行排队-您需要达到这样一个点,即每个单独的作业所涉及的任务比池中的线程多,因此,一些任务总是从队列中开始,而不是直接分配给线程(如果有空闲线程,则
exec.execute()
将任务直接传递给线程,而根本不经过队列)。

最简单的方法是超额订阅CPU,正如Kanaga所建议的,但是每个线程启动8个线程。竞争可能会带来一些开销,但如果您只处理一个作业,它将充分利用CPU。操作系统将为每个线程分配时间

你的“第一个想法”也会奏效。如果空闲线程没有实际执行任务,那么它们不会从8个工作线程获取资源。但是,当有多个作业在运行时,这并不能均匀地分配cpu资源


您是否有一个可以测试这些不同管道的设置,以了解它们对您的影响?

一种可能是根据作业数量调整工作人员的数量,并在工作人员多于核心时让操作系统处理时间切片。嗯,我不确定我是否理解。你的意思是,任务没有单线程吗?我不知道会有多少工作同时进行。通常只有一个,但在峰值可能有100个。这就是为什么我需要限制最多5个工作。因为通常一次只运行一个作业,所以我希望尽可能快地运行该作业,并使用尽可能多的线程运行该作业的tak(但只有当没有其他作业运行其单个任务时),三个作业只能使用三个线程。让每个作业线程在一个作业内执行任务时可以再生成四个线程。Kanaga。。。这就是我现在拥有的。有5个线程窥视作业的阻塞队列。当一个线程得到一个新任务时,它会启动多达四个并行工作线程来处理这个任务。当另一个作业线程偷看另一个作业时,它也会这样做。因此,当一次有两个作业时,就会出现并行线程,这是绝对完美的。但是,当一次只有一个作业时,它不会消耗全部cpu能量。因为只有四个线程,所以至少有两个内核没有被屏蔽。你能估计完成一项工作的时间吗?我也在考虑这个想法。但是当一个作业使用整个线程池时,这并没有帮助(正如您所说的)。所有即将到来的任务都必须等到这个大任务准备就绪。如果我事先知道作业是一个“大任务”,那么我可以减少工作线程的数量,以避免阻止正常作业的处理。也许我可以将我的委托界面扩展到as400.jobqueue,让我知道这份工作涵盖的月数。(会有效果,但还不是我想要的“最佳、摇摆、踢屁股的解决方案:-))谢谢……最后我选择了优先考虑的想法。跟你说的不完全一样。第二个答案的评论中有详细说明。是的,到目前为止,为每个作业启动8个线程都非常有效。但如上所述,当真的有三份工作时,这不是“摇摆”:-)
taskRunner.runTasks(jobTask1, jobTask2, jobTask3);