Почему newInstance создает исключение InstantiationException в моем коде?

У меня есть два процесса, как показано ниже. Каждый мой процесс имеет run а также shutdown метод

Process processA = new ProcessA("processA", getProcessAProperties());
Process processB = new ProcessB("processB", getProcessBProperties());
  • Я хочу иметь различную конфигурацию пула потоков для каждого Процесса, чтобы ProcessA запускалась в своем собственном пуле потоков, а ProcessB запускалась в своем собственном пуле потоков, независимо друг от друга.
  • И я не могу разделить объект Process между каждым потоком его собственного пула потоков.

Ниже показано, как выглядит мой класс Process, а мой ProcessA, ProcessB класс просто расширяет класс Process. И я делаю все важные вещи в моем методе бега.

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 учебный класс Process p = process.getClass().newInstance(); выдает исключение как:

java.lang.InstantiationException: com.david.test.ProcessA

Я не уверен почему InstantiationException бросают?

Просто примечание: каждый из этих процессов является потребителем kafka, и, как правило, потребитель kafka не является потокобезопасным, поэтому мне приходится каждый раз создавать новый объект и отправлять его исполнителю.

Обновить:

Это мой класс ProcessA выглядит так:

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

2 ответа

Решение

Есть ли у вас конкретный класс, который расширяет ваш абстрактный класс Process?

абстрактные классы не могут быть созданы сами по себе, см.: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

Возможно, попробуйте расширить ваш абстрактный класс конкретным классом и создать экземпляры вашего конкретного класса, но при необходимости вы все равно можете привести их как объект Process.

метод построения в ProcessA

 public ProcessA(String processName, Properties props);

поэтому не существует метода конструирования без аргументов, такого как:

 public ProcessA();

а также

 Process p = process.getClass().newInstance()

вызовет метод конструирования без аргументов, поэтому появится исключение.

для получения дополнительной информации: https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

Другие вопросы по тегам