I am trying to do a multi thread simulator where there are workers (threads) and jobs to solve, so every thread has to solve a job and start to solve the next
in order, the integer of the job is the time in seconds that is required to solve the job, this is a simulation so the code prints the index of the thread with
the initialization time of the job but it hasn't to be sleeping that number of seconds.

The problem is that i'm getting a NullPointerException only when there are a lot of jobs with the same number like
4 12 (4 threads for 12 jobs)
1 1 1 1 1 1 1 1 1 1 1 1 (12 jobs that require 1 second to be completed) it launches the exception in this part:

```
if (workersReady.size()>1) { 
              bestWorker = workersReady.iterator().next();
              workersReady.remove(bestWorker);
              workersReadyAtTimeT.remove(currentTime);
              workersReadyAtTimeT.put(currentTime,workersReady);
              nextTimesQueue.add(currentTime);

```

The input has to be like this:

First line:
2 5 It means that there are two threads(workers) for 5 jobs

Press enter and write the second line:
1 2 3 4 5 This is the jobs that are an integer which means the time cost of processing that job so the output after press enter will be this:

0 0 The two threads try to simultaneously take jobs from the list, so thread with index 0 actually
takes the first job and starts working on it at the moment 0

1 0 Thread with index 1 takes the first job and starts working on it at the moment 0

0 1 After 1 second, thread 0 is done with the first job and takes the third job from the list, and
starts processing it immediately at time 1.

1 2 One second later, thread 1 is done with the second job and takes the fourth job from the list, and starts processing it immediately at time 2

0 4 Finally, after 2 more seconds, thread 0 is done with the third job and takes the fifth job from the list, and starts processing it immediately at time 4

This is the code:

```
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());
        }
    }
}

```

Edit: I used a ConcurentHashMap and still launching NullPointer