1

У меня есть два процесса, как показано ниже. Каждый мой процесс имеет run и shutdown методПочему newInstance выбрасывает ExpressionException в моем коде?

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

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

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

Так, чтобы решить эту проблему в более общем плане, я создал обработчик процесса, как показано ниже:

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 не является потокобезопасным, поэтому я должен каждый раз создавать новый объект и подчиняться исполнителю.

Update:

Это мой класс 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 
    } 
} 
+0

абстрактные классы не могут быть созданы, через вопрос, хотя мне это нравится :) – HaydenKai

+0

Aahh .. Не знал, так как исправить этот вопрос сейчас? – john

+0

@ david мой ответ должен помочь – HaydenKai

ответ

1

ли вам конкретный класс, экстентов технологом абстрактный класс?

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

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

+0

Я обновил вопрос с помощью своего класса ProcessA. Я все еще путаюсь, как решить эту проблему? – john

+0

В принципе Если вы посмотрите на мой первый основной метод. Я хочу сделать то же самое, но более общим образом, чтобы я мог выполнять как ProcessA, так и ProcessB в своем пуле потоков. – john

+0

Вы можете вызвать конструктор no-arg с помощью .newInstance(): https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html – Jaxon

0

метод конструкции в ProcessA является

public ProcessA(String processName, Properties props); 

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

public ProcessA(); 

и

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

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

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

+0

Не работает. Я получаю эту ошибку: 'Метод newInstance() в типе Class не применим для аргументов (String, Properties) ' – john

Смежные вопросы