【发布时间】:2020-07-27 19:55:39
【问题描述】:
我正在尝试做一个多线程模拟器,其中有工人(线程)和要解决的工作,所以每个线程都必须解决一个工作并开始解决下一个 按顺序,作业的整数是解决作业所需的时间(以秒为单位),这是一个模拟,因此代码打印线程的索引 作业的初始化时间,但它没有休眠那么秒数。
问题是,只有当有很多具有相同编号的作业时,我才会收到 NullPointerException,例如 4 12(4 个线程用于 12 个作业) 1 1 1 1 1 1 1 1 1 1 1 1 (需要 1 秒才能完成的 12 个作业)它在这部分启动异常:
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
输入必须是这样的:
第一行: 2 5 表示 5 个作业有两个线程(worker)
按回车键并写入第二行: 1 2 3 4 5 这是一个整数的作业,这意味着处理该作业的时间成本,因此按 Enter 后的输出将是这样的:
0 0 两个线程试图同时从列表中获取作业,所以实际上索引为 0 的线程 接受第一份工作并在 0 时开始工作
1 0 索引为 1 的线程接受第一个作业并在 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());
}
}
}
编辑:我使用了 ConcurentHashMap 并仍在启动 NullPointer
【问题讨论】:
标签: java multithreading algorithm hashmap queue