为什么 newInstance 在我的代码中抛出 InstantiationException?
Why newInstance throws InstantiationException in my code?
我有两个过程,如下所示。我的每个进程都有 run
和 shutdown
方法
Process processA = new ProcessA("processA", getProcessAProperties());
Process processB = new ProcessB("processB", getProcessBProperties());
- 我想为每个进程配置不同的线程池,以便 ProcessA 运行 在其自己的线程池中和 ProcessB 运行 在其自己的线程池中相互独立。
- 而且我不能在它自己的线程池的每个线程之间共享 Process 对象。
下面是我的进程 class 的样子,而我的 ProcessA
、ProcessB
class 只是扩展了进程 class。我在 运行 方法中做了所有重要的事情。
public abstract class Process implements Runnable {
private Properties props;
private String processName;
public Process(String processName, Properties props) {
this.processName = processName;
this.props = props;
}
protected abstract void shutdown();
protected abstract void run(String processName, Properties props);
@Override
public final void run() {
run(processName, props);
}
public Properties getProps() {
return props;
}
public void setProps(Properties props) {
this.props = props;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
}
下面是一个简单示例,说明我如何 运行 使用自己的线程池 ProcessA
。 有三个线程,每个线程都有自己的 ProcessA 对象来处理。现在我想以更通用的方式扩展它,以便它可以为我的两个进程工作ProcessA
和 ProcessB
.
public static void main(String[] args) {
int numberOfThreads = 3;
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
final List<Process> processes = new ArrayList<>();
for (int i = 0; i < numberOfThreads; i++) {
// each thread works on different Process object
Process processA = new ProcessA("processA", getProcessAProperties());
processes.add(processA);
executor.submit(processA);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
for (Process process : processes) {
process.shutdown();
}
executor.shutdown();
try {
executor.awaitTermination(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace;
}
}
});
}
因此,为了以更通用的方式解决这个问题,我创建了一个 Process 处理程序,如下所示:
public final class ProcessHandler {
private final ExecutorService executorServiceProcess;
private final List<Process> processes = new ArrayList<>();
private final Thread shutdownHook = new Thread() {
@Override
public void run() {
for (Process process : processes)
process.shutdown();
executorServiceProcess.shutdown();
}
};
public ProcessHandler(Process process, int poolSize) {
this.executorServiceProcess = Executors.newFixedThreadPool(poolSize);
Runtime.getRuntime().addShutdownHook(shutdownHook);
for (int i = 0; i < poolSize; i++) {
try {
// this line throws exception
Process p = process.getClass().newInstance();
p.setProcessName(process.getProcessName());
p.setProps(process.getProps());
processes.add(p);
executorServiceProcess.submit(p);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
public void shutdown() {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
shutdownHook.start();
try {
shutdownHook.join();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
这是我的主要方法现在的样子:
public static void main(String[] args) {
Process processA = new ProcessA("processA", getProcessAProperties());
Process processB = new ProcessB("processB", getProcessBProperties());
// processA will run with three threads in its own thread pool
ProcessHandler processHandlerA = new ProcessHandler (processA, 3);
// processB will run with two threads in its own thread pool
ProcessHandler processHandlerB = new ProcessHandler (processB, 2);
// now I can call shutdown on them
processHandlerA.shutdown();
processHandlerB.shutdown();
}
我的 ProcessHandler
class Process p = process.getClass().newInstance();
中的这一行抛出异常为:
java.lang.InstantiationException: com.david.test.ProcessA
我不确定为什么 InstantiationException
会被抛出?
请注意:这些进程中的每一个都是 kafka 消费者,通常 kafka 消费者不是线程安全的,所以这就是为什么我每次都必须创建一个新对象并提交给执行程序。
更新:
这是我的流程 A class 看起来像:
public class ProcessA extends Process {
private KafkaConsumer<byte[], byte[]> consumer;
public ProcessA(String processName, Properties props) {
super(processName, props);
}
@Override
public void shutdown() {
consumer.wakeup();
}
@Override
protected void run(String processName, Properties props) {
consumer = new KafkaConsumer<>(props);
System.out.println("Hello World");
// do all kind of important stuff here
}
}
你有具体的 class 扩展你的过程抽象 class 吗?
抽象classes不能自己实例化,见:http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
也许尝试用具体 class 扩展抽象 class 并创建具体 class 的实例,如果需要,您仍然可以将它们转换为 Process 对象。
进程A中的构造函数是
public ProcessA(String processName, Properties props);
所以不存在像这样的无参数构造函数:
public ProcessA();
和
Process p = process.getClass().newInstance()
会调用一个不存在的无参构造方法,所以会出现异常。
更多信息,请查看https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html。
我有两个过程,如下所示。我的每个进程都有 run
和 shutdown
方法
Process processA = new ProcessA("processA", getProcessAProperties());
Process processB = new ProcessB("processB", getProcessBProperties());
- 我想为每个进程配置不同的线程池,以便 ProcessA 运行 在其自己的线程池中和 ProcessB 运行 在其自己的线程池中相互独立。
- 而且我不能在它自己的线程池的每个线程之间共享 Process 对象。
下面是我的进程 class 的样子,而我的 ProcessA
、ProcessB
class 只是扩展了进程 class。我在 运行 方法中做了所有重要的事情。
public abstract class Process implements Runnable {
private Properties props;
private String processName;
public Process(String processName, Properties props) {
this.processName = processName;
this.props = props;
}
protected abstract void shutdown();
protected abstract void run(String processName, Properties props);
@Override
public final void run() {
run(processName, props);
}
public Properties getProps() {
return props;
}
public void setProps(Properties props) {
this.props = props;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
}
下面是一个简单示例,说明我如何 运行 使用自己的线程池 ProcessA
。 有三个线程,每个线程都有自己的 ProcessA 对象来处理。现在我想以更通用的方式扩展它,以便它可以为我的两个进程工作ProcessA
和 ProcessB
.
public static void main(String[] args) {
int numberOfThreads = 3;
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
final List<Process> processes = new ArrayList<>();
for (int i = 0; i < numberOfThreads; i++) {
// each thread works on different Process object
Process processA = new ProcessA("processA", getProcessAProperties());
processes.add(processA);
executor.submit(processA);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
for (Process process : processes) {
process.shutdown();
}
executor.shutdown();
try {
executor.awaitTermination(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace;
}
}
});
}
因此,为了以更通用的方式解决这个问题,我创建了一个 Process 处理程序,如下所示:
public final class ProcessHandler {
private final ExecutorService executorServiceProcess;
private final List<Process> processes = new ArrayList<>();
private final Thread shutdownHook = new Thread() {
@Override
public void run() {
for (Process process : processes)
process.shutdown();
executorServiceProcess.shutdown();
}
};
public ProcessHandler(Process process, int poolSize) {
this.executorServiceProcess = Executors.newFixedThreadPool(poolSize);
Runtime.getRuntime().addShutdownHook(shutdownHook);
for (int i = 0; i < poolSize; i++) {
try {
// this line throws exception
Process p = process.getClass().newInstance();
p.setProcessName(process.getProcessName());
p.setProps(process.getProps());
processes.add(p);
executorServiceProcess.submit(p);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
public void shutdown() {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
shutdownHook.start();
try {
shutdownHook.join();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
这是我的主要方法现在的样子:
public static void main(String[] args) {
Process processA = new ProcessA("processA", getProcessAProperties());
Process processB = new ProcessB("processB", getProcessBProperties());
// processA will run with three threads in its own thread pool
ProcessHandler processHandlerA = new ProcessHandler (processA, 3);
// processB will run with two threads in its own thread pool
ProcessHandler processHandlerB = new ProcessHandler (processB, 2);
// now I can call shutdown on them
processHandlerA.shutdown();
processHandlerB.shutdown();
}
我的 ProcessHandler
class Process p = process.getClass().newInstance();
中的这一行抛出异常为:
java.lang.InstantiationException: com.david.test.ProcessA
我不确定为什么 InstantiationException
会被抛出?
请注意:这些进程中的每一个都是 kafka 消费者,通常 kafka 消费者不是线程安全的,所以这就是为什么我每次都必须创建一个新对象并提交给执行程序。
更新:
这是我的流程 A class 看起来像:
public class ProcessA extends Process {
private KafkaConsumer<byte[], byte[]> consumer;
public ProcessA(String processName, Properties props) {
super(processName, props);
}
@Override
public void shutdown() {
consumer.wakeup();
}
@Override
protected void run(String processName, Properties props) {
consumer = new KafkaConsumer<>(props);
System.out.println("Hello World");
// do all kind of important stuff here
}
}
你有具体的 class 扩展你的过程抽象 class 吗?
抽象classes不能自己实例化,见:http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
也许尝试用具体 class 扩展抽象 class 并创建具体 class 的实例,如果需要,您仍然可以将它们转换为 Process 对象。
进程A中的构造函数是
public ProcessA(String processName, Properties props);
所以不存在像这样的无参数构造函数:
public ProcessA();
和
Process p = process.getClass().newInstance()
会调用一个不存在的无参构造方法,所以会出现异常。
更多信息,请查看https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html。