英文:
NullPointerException when shutting down thread pool
问题
我有一个线程池,我正在尝试关闭它,但是我遇到了以下错误:
java.lang.NullPointerException
at Terminate.action(Terminate.java:8)
at Event.run(Event.java:63)
at java.base/java.lang.Thread.run(Thread.java:832)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
线程池在继承了Event的Restart类中定义:
public class Restart extends Event {
// ...(代码部分省略)
}
关闭操作在以下位置被调用:
public class Terminate extends Event {
// ...(代码部分省略)
}
Event.java:
public abstract class Event implements Runnable {
// ...(代码部分省略)
}
我不太确定是什么原因导致了这个错误,尝试过改变线程池的定义方式以及何时调用shutdown,但并没有真正改变什么。有没有什么想法是什么原因并且如何修复?
提前感谢您的帮助。
英文:
I have thread pool that i'm trying to shutdown but i'm getting the following error:
java.lang.NullPointerException
at Terminate.action(Terminate.java:8)
at Event.run(Event.java:63)
at java.base/java.lang.Thread.run(Thread.java:832)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
the thread pool is defined in Restart() extends Event:
public class Restart extends Event {
private static String eventsFile;
ArrayList<String> eventList = new ArrayList<>();
ArrayList<Integer> timeList = new ArrayList<>();
public int rings = 1;
GreenhouseControls greenhouseControls = new GreenhouseControls();
public Restart(long delayTime, String filename) {
super(delayTime);
eventsFile = filename;
}
// action was modified to read text file and add events indicated in file
public void action() {
File file = new File(eventsFile);
try {
Scanner scanner = new Scanner(file);
while(scanner.hasNext()){
String eventLine = scanner.nextLine();
// Using regex to identify events, delay time and number of rings in txt file
Pattern pattern = Pattern.compile("^Event=(?<event>[^,]*),time=(?<time>[^,]*)(,rings=(?<ring>[^,]*))?$");
Matcher matcher = pattern.matcher(eventLine);
// store delay time and number of rings in their respective variables.
while (matcher.find()) {
String eventName = matcher.group("event");
int time = Integer.parseInt(matcher.group("time"));
if (matcher.group("ring") != null) {
rings = Integer.parseInt(matcher.group("ring"));
}
eventList.add(eventName);
timeList.add(time);
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
pool = Executors.newFixedThreadPool(timeList.size());
for (int i = 0; i < eventList.size(); i++) {
Class<?> eventClass;
try {
eventClass = Class.forName(eventList.get(i));
Object eventObject;
if (eventList.get(i).equals("Bell")) {
eventObject = eventClass.getConstructor(long.class, int.class).newInstance(timeList.get(i), rings);
}
else {
eventObject = eventClass.getConstructor(long.class).newInstance(timeList.get(i));
}
Thread eventThread = new Thread((Runnable) eventObject);
//eventThread.start();
pool.execute(eventThread);
}
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
System.out.println(pool);
}
public String toString() {
return "Restarting system";
}
}
and the shutdown is being called here:
public class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
public void action() {
pool.shutdown();
}
public String toString() {
return "Terminating";
}
}
Event.java:
public abstract class Event implements Runnable {
private long eventTime;
protected final long delayTime;
public ExecutorService pool;
GreenhouseControls greenhouseControls = new GreenhouseControls();
public String errorMessage;
boolean suspend;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public synchronized void isSuspended() {
suspend = greenhouseControls.getSuspend();
notifyAll();
}
public void run() {
try {
while (suspend) {
try {
synchronized(this) {
wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.sleep(delayTime);
}
catch (InterruptedException e) {
pool.shutdown();
}
try {
System.out.println(this.toString());
this.action();
}
catch (Exception e) {
e.printStackTrace();
}
}
public abstract void action() throws GreenhouseControls.ControllerException;
} ///:~
I'm not really sure what's causing it and tried changing how the pool is defined and where I call shutdown but nothing really changed. any idea what's causing it and how to fix it?
Thanks in advance.
答案1
得分: 0
问题:为什么会抛出 NullPointerException
?
嗯,在你的抽象类 Event
中,你声明了一个 ExecutorService
:
public ExecutorService pool;
但在那两个子类 Terminate
和 Restart
中,pool
只在 Restart
中初始化,在 Terminate
中仍然指向 null
。
因此,当你尝试调用 action
时,对于 pool
的引用为 null,因此抛出了 NullPointerException
。
相反地,
在你的抽象类中初始化并赋值给 ExecutorService
,然后将这个池共享给你的子类。
public abstract class Event implements Runnable {
...
public ExecutorService pool;
...
public void setExecutorService(int size) {
pool = Executors.newFixedThreadPool(size);
}
}
public class Restart extends Event {
...
setExecutorService(timeList.size());
...
}
英文:
Question: Why `NullPointerException` was thrown?
Well, in your abstract class Event
you have declared your ExecutorService
public ExecutorService pool;
But among those two child classes Terminate
and Restart
, the pool was initialized only in Restart
but in Terminate
it is still pointing to null
So, when you try to call action
the ref to pool was null and hence NullPointerException
was thrown.
Instead,
Initialize and assign the value to ExecutorService
in your abstract class itself and share the pool to your child classes.
public abstract class Event implements Runnable {
...
public ExecutorService pool;
...
public void setExecutorService(int size) {
pool = Executors.newFixedThreadPool(size);
}
}
public class Restart extends Event {
...
setExecutorService(timeList.size());
...
}
专注分享java语言的经验与见解,让所有开发者获益!
评论