如何在Java中优化此模拟?

如何在Java中优化此模拟?,java,multithreading,algorithm,optimization,data-structures,Java,Multithreading,Algorithm,Optimization,Data Structures,我正在尝试用Java做一个多线程模拟,我已经设法用一个队列来做了,但是执行时间很长,有没有办法优化它?使用递归可以节省时间吗 输入必须如下所示: private void assignJobs() { assignedWorker = new int[jobs.length]; startTime = new long[jobs.length]; PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Inte

我正在尝试用Java做一个多线程模拟,我已经设法用一个队列来做了,但是执行时间很长,有没有办法优化它?使用递归可以节省时间吗

输入必须如下所示:

private void assignJobs() {

 assignedWorker = new int[jobs.length];
 startTime = new long[jobs.length];
 PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
 HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
 long[] nextFreeTime = new long[numWorkers];
 int duration = 0;
 int bestWorker = 0;
 for (int i = 0; i < jobs.length; i++) {
  duration = jobs[i];
  if(i<numWorkers) {
    bestWorker = i;
    nextTimesQueue.add(duration);
    addToSet(workersReadyAtTimeT, duration, i,0);
  }else {
    int currentTime = nextTimesQueue.poll();
    Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
    if (workersReady.size()>1) { 
      bestWorker = workersReady.iterator().next();
      workersReady.remove(bestWorker);
      workersReadyAtTimeT.remove(currentTime);
      workersReadyAtTimeT.put(currentTime,workersReady);
      nextTimesQueue.add(currentTime);
    } else {
      bestWorker = workersReady.iterator().next();
      workersReadyAtTimeT.remove(currentTime);
      nextTimesQueue.add(currentTime+duration);
      addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
    }
  }
  assignedWorker[i] = bestWorker;
  startTime[i] = nextFreeTime[bestWorker];
  nextFreeTime[bestWorker] += duration;
 }
}

private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
  HashSet<Integer> s = new HashSet<Integer>();
  s.add(worker);
  workersReadyAtTimeT.put(current+duration, s);
}else {
  Set<Integer> s = workersReadyAtTimeT.get(current+duration);
  s.add(worker);
  workersReadyAtTimeT.put(current+duration,s);
 }
}
  • 2.5这意味着5个作业有两个线程(工作线程)
  • 1 2 3 4 5这是整数作业,表示处理该作业的时间成本,因此输出如下:
  • 0两个线程试图同时从列表中获取作业,因此实际上索引为0的线程
  • 1 0接受第一个作业,并在0时刻开始处理该作业
  • 0 1 1秒后,线程0完成第一个作业并从列表中获取第三个作业,并在时间1立即开始处理它
  • 1 2一秒钟后,线程1处理完第二个作业,从列表中取出第四个作业,并在时间2立即开始处理它
  • 0 4最后,再过2秒,线程0完成第三个作业并从列表中获取第五个作业,并在时间4立即开始处理它
代码如下:

import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;

public class JobQueue {
    private int numWorkers;
    private int[] jobs;
    private int[] assignedWorker;
    private long[] startTime;

    private FastScanner in;
    private PrintWriter out;

    public static void main(String[] args) throws IOException {
        new JobQueue().solve();
    }

    private void readData() throws IOException {
        numWorkers = in.nextInt();
        int m = in.nextInt();
        jobs = new int[m];
        for (int i = 0; i < m; ++i) {
            jobs[i] = in.nextInt(); 
        }
    }

    private void writeResponse() {
        for (int i = 0; i < jobs.length; ++i) {
            out.println(assignedWorker[i] + " " + startTime[i]);
        }
    }

    private void assignJobs() {
        // TODO: replace this code with a faster algorithm.
        assignedWorker = new int[jobs.length];
         startTime = new long[jobs.length];
         PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
         HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
         long[] nextFreeTime = new long[numWorkers];
         int duration = 0;
         int bestWorker = 0;
         for (int i = 0; i < jobs.length; i++) {
          duration = jobs[i];
          if(i<numWorkers) {
            bestWorker = i;
            nextTimesQueue.add(duration);
            addToSet(workersReadyAtTimeT, duration, i,0);
          }else {
            int currentTime = nextTimesQueue.poll();
            Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
            if (workersReady.size()>1) { 
              bestWorker = workersReady.iterator().next();
              workersReady.remove(bestWorker);
              workersReadyAtTimeT.remove(currentTime);
              workersReadyAtTimeT.put(currentTime,workersReady);
              nextTimesQueue.add(currentTime);
            } else {
              bestWorker = workersReady.iterator().next();
              workersReadyAtTimeT.remove(currentTime);
              nextTimesQueue.add(currentTime+duration);
              addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
            }
          }
          
          assignedWorker[i] = bestWorker;
          startTime[i] = nextFreeTime[bestWorker];
          nextFreeTime[bestWorker] += duration;
         }
        }
    
    private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
        if(workersReadyAtTimeT.get(current+duration)==null) {
          HashSet<Integer> s = new HashSet<Integer>();
          s.add(worker);
          workersReadyAtTimeT.put(current+duration, s);
        }else {
          Set<Integer> s = workersReadyAtTimeT.get(current+duration);
          s.add(worker);
          workersReadyAtTimeT.put(current+duration,s);
         }
        }

    public void solve() throws IOException {
        in = new FastScanner();
        out = new PrintWriter(new BufferedOutputStream(System.out));
        readData();
        assignJobs();
        writeResponse();
        out.close();
    }

    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public FastScanner() {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
        }

        public String next() throws IOException {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                tokenizer = new StringTokenizer(reader.readLine());
            }
            return tokenizer.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
    }
}
 
import java.io.*;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.PriorityQueue;
导入java.util.Set;
导入java.util.StringTokenizer;
公共类工作队列{
私人内勤人员;
私人职位;
私人int[]指定工人;
私人长[]起始时间;
私人快速扫描仪;
私人打印输出;
公共静态void main(字符串[]args)引发IOException{
新建作业队列().solve();
}
私有void readData()引发IOException{
numWorkers=in.nextInt();
int m=in.nextInt();
作业=新整数[m];
对于(int i=0;i
在我看来,您的
jobsList
对象是完全冗余的,它包含的所有内容也都在
jobs
数组中,当您使用前面的元素时,您将在
jobs[i]
处获得项目。为了加快一点速度,您可以将int的构造函数从循环中去掉,只需为它们分配新的数字。另一个优化是在第一个
numWorkers
作业期间不进行搜索,因为您知道在对资源池进行检查之前,您仍然有空闲的工作人员。一旦你找到了一个好员工,你就不必一直寻找,这样你就可以
继续
跳出for循环

public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;

    private void readData() throws IOException {
    numWorkers = in.nextInt();
    int m = in.nextInt();
    jobs = new int[m];
    for (int i = 0; i < m; ++i) {
        jobs[i] = in.nextInt();
    }
}

private void assignJobs() {
    assignedWorker = new int[jobs.length];
    startTime = new long[jobs.length];
    long[] nextFreeTime = new long[numWorkers];
    int duration = 0;
    int bestWorker = 0;
    for (int i = 0; i < jobs.length; i++) {
        duration = jobs[i];
        bestWorker = 0;
        if (i< numWorkers){
            bestWorker= i;
        } else{
            for (int j = 0; j < numWorkers; ++j) {
                if (nextFreeTime[j] < nextFreeTime[bestWorker])
                    bestWorker = j;
                    continue;
            }
        }
        assignedWorker[i] = bestWorker;
        startTime[i] = nextFreeTime[bestWorker];
        nextFreeTime[bestWorker] += duration;
    }
}
公共类作业队列{
私人内勤人员;
私人职位;
私人int[]指定工人;
私人长[]起始时间;
私有void readData()引发IOException{
numWorkers=in.nextInt();
int m=in.nextInt();
作业=新整数[m];
对于(int i=0;i