本文介绍了使用ConcurrentHashMap更新了NullPointerException问题的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试做一个多线程模拟器,其中有要解决的工作人员(线程)和工作,因此每个线程都必须解决一个工作并开始解决下一个问题按顺序,作业的整数是解决作业所需的时间(以秒为单位),这是一个模拟,因此代码使用以下命令打印线程的索引作业的初始化时间,但不必等待那么多秒数.

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 nextin 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 withthe initialization time of the job but it hasn't to be sleeping that number of seconds.

问题是仅当有很多相同编号的工作时,我才得到NullPointerException4 12(4个线程可处理12个工作)1 1 1 1 1 1 1 1 1 1 1 1 1(需要完成1秒才能完成的12个作业)会在本部分中引发异常:

The problem is that i'm getting a NullPointerException only when there are a lot of jobs with the same number like4 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);

输入必须像这样:

第一行:2 5表示有5个工作的两个线程(工作人员)

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

按Enter键并写第二行:1 2 3 4 5这是一个整数作业,表示处理该作业的时间成本,因此按Enter键后的输出为:

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两个线程试图同时从列表中获取作业,因此实际上索引为0的线程接受第一份工作,并从0开始进行工作

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

1 0索引为1的线程执行第一个作业,并在0时刻开始对其进行处理

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

0 1 1秒后,线程0完成了第一个作业,并从列表中获取了第三个作业,并且从时间1开始立即处理它.

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

1 2一秒钟后,线程1完成了第二个作业,并从列表中获取了第四个作业,并在时刻2立即开始处理它.

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最后,再经过2秒后,线程0完成了第三项工作,并从列表中获取了第五项工作,并在时刻4立即开始处理它.

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

这是代码:

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

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>();
         ConcurrentHashMap<Integer, Set<Integer>> workersReadyAtTimeT = new ConcurrentHashMap<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(ConcurrentHashMap<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());
        }
    }
}
 

我使用了ConcurentHashMap并仍在启动NullPointer

I used a ConcurentHashMap and still launching NullPointer

推荐答案

我敢打赌这会引起一些问题:

I bet this is causing some problem:

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

首先,我将空检查您要获取的Set.

First of all, I would null-check the Set you are trying to get.

此外,如果您选中size()>1,则当准备好 2位工作人员时,这将是真的,而不仅仅是一个.如果要检查是否只有一个就绪,则条件应该为size()>0或仅为!isEmpty().

Also, if you check size()>1 it will be true when there are 2 workers ready, not only one. If you wish to check if just one is ready, the condition should be size()>0, or just !isEmpty().

类似的东西:

 Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
 if (workersReady!=null && !workersReady.isEmpty()) 
 { 
     bestWorker = workersReady.iterator().next();
     workersReady.remove(bestWorker);
     workersReadyAtTimeT.remove(currentTime);
     workersReadyAtTimeT.put(currentTime,workersReady);
     nextTimesQueue.add(currentTime);
 }

此后,您不应在此行中得到任何NullPointer,希望对您有所帮助.

You shouldn't be getting any NullPointer in this line after this, hope it helps.

这篇关于使用ConcurrentHashMap更新了NullPointerException问题的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 09:19