问题描述
我正在尝试做一个多线程模拟器,其中有要解决的工作人员(线程)和工作,因此每个线程都必须解决一个工作并开始解决下一个问题按顺序,作业的整数是解决作业所需的时间(以秒为单位),这是一个模拟,因此代码使用以下命令打印线程的索引作业的初始化时间,但不必等待那么多秒数.
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问题的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!