【问题标题】:java priority queue to queue adaptationjava优先级队列到队列适配
【发布时间】:2013-02-21 12:53:46
【问题描述】:

我有一个优先级队列,它按日期顺序列出来自 sql 数据库的大量作业。然后我得到了最接近的DeadlineJob函数,它得到了最高职位,检查是否有任何其他工作具有相同的日期,然后比较优先级以查看哪个是最高职位。然后我得到了最高职位。

查找原始队列顶部作业:

public JobRequest closestDeadlineJob(int freeCPUS) {
        // find top job to determine if other jobs for date need to be considered
        JobRequest nextJob = scheduledJobs.peek(); // return top most job

        if (nextJob != null) {

            System.out.println("Found top EDF job:");
            printJob( nextJob );

            // what is it's date?
            Date highestRankedDate = nextJob.getConvertedDeadlineDate();

            // create a temporary queue to work out priorities of jobs with same deadline
            JobPriorityQueue schedulerPriorityQueue = new JobPriorityQueue();

            // add the top job to priority queue
            //schedulerPriorityQueue.addJob(nextJob);

            for (JobRequest jr : scheduledJobs) {

                // go through scheduled jobs looking for all jobs with same date
                if (jr.getConvertedDeadlineDate().equals(highestRankedDate)) {
                    // same date deadline, soadd to scheduler priority queue
                    schedulerPriorityQueue.addJob(jr);
                    System.out.println("Adding following job to priority queue:");
                    printJob(jr);
                }
            }

            JobRequest highestPriorityJob = schedulerPriorityQueue.poll();
            // this is the item at the top of the PRIORTY JOB queue to return 

            // remove that item from scheduledJobs
            scheduledJobs.remove(highestPriorityJob);


            return highestPriorityJob;
        } else {
            return null;
        }
    }

以下代码将顶级作业处理到队列中:

    public void processNextJob() {
        /*
         * 1. get # of free CPU's still avaialble
         * 2. get top most job from priority queue
         * 3. run job - put to CPU queue
         * 4. develop a CPU queue here
         * 5. count cores against freeCPUS and some sort of calculation to sort run times
         */
        int freeCPUS = 500;
        int availableCPUS = 0;
        Queue q = new PriorityQueue();

//        while(freeCPUS >= 500)
//        {
//           
//        }


        JobRequest nextJob = schedulerPriorityQueue.closestDeadlineJob(freeCPUS); // returns top job from queue
        if (nextJob != null) {
            System.out.println("Top priority / edf job:");
            System.out.print(nextJob.getUserID() + "-->");
            System.out.print(nextJob.getStartDate() + "--START-->");
            System.out.print(nextJob.getEndDate() + "---END-->");
            System.out.print(nextJob.getDeadDate() + "--DROP-->");
            System.out.print(nextJob.getDepartment() + "-->");
            System.out.print(nextJob.getProjectName() + "-->");
            System.out.print(nextJob.getProjectApplication() + "-->");
            System.out.print(nextJob.getPriority() + "--PRIORITY-->");
            System.out.print(nextJob.getCores() + "-->");
            System.out.print(nextJob.getDiskSpace() + "-->");
            System.out.println(nextJob.getAnaylsis());

            // now got correct job based on earliest deadline / priority
            // implement a FIFO queue here / execution stack
            // add next job here
        } else {
            System.out.println("Job = null");
        } 

    }

我需要做的是修复我的不良尝试或适应,将我的最接近的DeadlineJob 中的作业放入队列,然后在我达到 500 个核心限制时停止将它们放入队列中。目前我只是卡在了 while true 下面的 for 循环中,我认为我设定的方式在离开循环后甚至都行不通。

有什么想法吗?

编辑

public void processNextJob() {
        /*
         * 1. get # of free CPU's still avaialble
         * 2. get top most job from priority queue
         * 3. run job - put to CPU queue
         * 4. develop a CPU queue here
         * 5. count cores against freeCPUS and some sort of calculation to sort run times
         */
        int freeCPUS = 500;
        int availableCPUS = 0;

        JobRequest nextJob = schedulerPriorityQueue.closestDeadlineJob(freeCPUS); // returns top job from queue
        if (nextJob != null) {
            System.out.println("Top priority / edf job:");
            printJob( nextJob );
            // go through scheduled jobs looking for all jobs with same date
            if (nextJob.getCores() <= freeCPUS) {
                // same date deadline, soadd to scheduler priority queue
                schedulerPriorityQueue.addJob(nextJob);
                System.out.println("Adding following job to execution queue:");
                printJob( nextJob );     
                // can use this to get the next top job but need to add calculations to printout the next top job aslong as CPU less than 500
//                schedulerPriorityQueue.closestDeadlineJob(freeCPUS);
//                schedulerPriorityQueue.addJob(nextJob);
            } else if (nextJob.getCores() > freeCPUS) {
                System.out.println("Queue temporarily full");
            }
            // now got correct job based on earliest deadline / priority
            // implement a FIFO queue here / execution stack
            // add next job here
        } else {
            System.out.println("Job = null");
        }

    }

我想我需要在上面实现一个循环并移出 if 语句说接受下一项工作,如果低于 500,则再次循环并获得另一个然后将其放入某种新队列中,当满足 500 个核心条件时停止添加到新队列

【问题讨论】:

  • 没有真正回答这个问题,但是您是否有理由不能在 SQL 中对数据进行更多过滤?
  • 另外,当所有 500 个(!?)核心都忙时应该是什么行为?新工作应该被拒绝还是排队?
  • 由于限制和设置方式不,我只需要将“x”数量的作业添加到队列中(不知道哪种类型最好),核心限制低于 500 并且当它不能再从队列中添加或者它已满时停止添加,直到空间变得可用。他们将留在原始队列中,直到有空间可以将它们放入我试图在此处设置的“执行队列”中
  • 所以它的设置方式是我有一个排序的priorityQueue,priortyQueue中的每个项目都有自己的核心,有些有100个或有些多或少,我只想添加“x " 从我的最接近的DeadlineJob 到队列的作业数量,其中排序下一个顶级作业,当 .getCores 达到 500 或足够接近时,下一个作业无法运行,然后停止从优先队列添加到队列
  • 你应该直接在 SQL 中进行所有这些排序和分组,并去掉所有的乱码。

标签: java queue priority-queue


【解决方案1】:

我会尽可能使用java.util.concurrent 包中的实用程序。

首先,您可以定义 PriorityBlockingQueue 和 Comparator,按日期然后优先级对作业进行排序,因此具有最早日期和最高优先级的作业始终位于队列的开头:

PriorityBlockingQueue<JobRequest> q = new PriorityBlockingQueue<Test1.JobRequest>(0, new Comparator<JobRequest>()
  {
    @Override
    public int compare(JobRequest o1, JobRequest o2)
    {
      int dateComparison = o1.getDate().compareTo(o2.getDate());
      if (dateComparison != 0)
        return dateComparison;
      // assume higher number means higher priority
      return o2.getPriority() - o1.getPriority();
    }
  });

我仍然不确定我是否了解您对内核的要求,但您有两种选择。如果您希望最多同时执行 500 个作业,则拒绝新项目,您可以使用带有 SynchronousQueue 的执行器:

ExecutorService executor = new ThreadPoolExecutor(0 /*core size*/, 
                                                  500 /*max size*/, 
                                                  0 /*keep alive*/, 
                                                  TimeUnit.SECONDS, 
                                                  new SynchronousQueue<Runnable>());

或者,如果您希望同时执行更少的作业,您可以使用ArrayBlockingQueue,它会在满时阻塞:

ExecutorService executor = new ThreadPoolExecutor(0 /*core size*/, 
                                                  5 /*max size*/, 
                                                  0 /*keep alive*/, 
                                                  TimeUnit.SECONDS, 
                                                  new ArrayBlockingQueue(500-5)<Runnable>());

然后从队列中拉出作业并执行它们,处理被拒绝的执行,但是你想:

while (!isFinished)
{
  JobRequest job = q.take();
  try
  {
    executor.execute(job);
  }
  catch (RejectedExecutionException e)
  {

  }
}

但是,如果您只想同时运行 500 个作业并且后续作业排队,只需传入 LinkedBlockingQueue 或使用 Executors 上的实用方法之一,例如 newFixedThreadPool(int nThreads)。

【讨论】:

  • 感谢 Simon,我已经编辑了有关 processingNextJob 的第二个代码示例,目的是在其中放置一个循环,将该作业放入队列中,就像您之前提到的那样,然后计数它需要的核心数量,例如总共 500 个,在最高工作之后是 400 个,所以循环返回并获取下一个工作,需要 300 个,将工作添加到队列中,让我剩下 100 个,去检查下一个工作,它的 200 个核心,将该工作留在队列中并搜索下一个需要 100 的可用,将其放入新队列中,这样更有意义吗?
  • 澄清一下,当您谈论 500 个内核时,您真的是指您想要一个同时运行 500 个线程的池吗?或者“核心”是否意味着其他东西?如果是前者,那么您可以通过executor.getMaximumPoolSize() - executor.getActiveCount() 大致了解您有多少备用线程。然后,您可以遍历q 并删除第一个getCoreRequirement 小于可用线程数的作业。如果您能解释一下这种设计背后的动机,可能会有所帮助?
  • 不,核心只是数据库中一个表的名称,它只是一个工作的标准值,我在原始问题上添加了一个编辑,现在我只需要它来添加top top 到队列中并继续添加下一个顶部作业和下一个作业,直到满足 500 个条件,所以我想象一个 while 循环,然后将一些东西放入队列中以保存作业,然后计算剩下多少,但不确定如何这样做,这是我正在尝试为我承担的一个小项目实现的一个额外功能
【解决方案2】:

找到解决我的问题的方法:

public void processNextJob() {
        /*
         * 1. get # of free CPU's still avaialble
         * 2. get top most job from priority queue
         * 3. run job - put to CPU queue
         * 4. develop a CPU queue here
         * 5. count cores against freeCPUS and some sort of calculation to sort run times
         */
        int freeCPUS = 500;
        int availableCPUS = 0;
        JobRequest temp = new JobRequest();
        Queue q = new LinkedList();

        while (true) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                temp = (JobRequest) q.peek();
                if (temp != null) {
                    availableCPUS += temp.getCores();
                }
            }
            if ((freeCPUS - availableCPUS) >= 0) {
                JobRequest nextJob = schedulerPriorityQueue.closestDeadlineJob(freeCPUS - availableCPUS); // returns top job from queue
                if (nextJob != null) {
                    System.out.println("Top priority / edf job:");
                    printJob(nextJob);
                    q.add(nextJob);

                } else {
                    System.out.println("Job = null");
                }

            } else {
                break;
            }
        }
        if (temp != null) {


            System.out.println("Execution Queue");
            System.out.println(q);

        }


    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 2012-09-23
    相关资源
    最近更新 更多