1

我有兩個過程如下所示。我的每一個過程都有runshutdown方法爲什麼newInstance在我的代碼中拋出InstantiationException?

Process processA = new ProcessA("processA", getProcessAProperties()); 
Process processB = new ProcessB("processB", getProcessBProperties()); 
  • 我想爲每個進程不同的線程池配置,以便ProcessA在自己的線程池運行和進程B在自己的線程池中運行相互獨立的。
  • 而且我無法在自己的線程池的每個線程之間共享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對象可供使用。現在我想以更通用的方式擴展它,以便它可以適用於我的流程ProcessAProcessB

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

此行在我的ProcessHandlerProcess p = process.getClass().newInstance();引發異常爲:

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

我不知道爲什麼InstantiationException被拋出?

只是一個說明:這些進程中的每一個都是卡夫卡消費者,通常卡夫卡消費者不是線程安全的,所以我必須每次創建一個新對象並提交給執行者。

更新:

這是我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

啊哈..沒讀過那麼現在該怎麼解決這個問題? – john

+0

@david我的回答應該幫助 – HaydenKai

回答

1

你說你的程度處理抽象類的具體類?

抽象類不能對自己進行實例化,請參閱:http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

也許嘗試用一個具體的類擴展您的抽象類和創建具體的類的實例,如果需要的話,你仍然可以施展他們作爲一個Process對象。

+0

我已經用我的ProcessA類更新了這個問題。我仍然困惑如何解決這個問題? – john

+0

基本上如果你看看我的第一個主要方法。我想做一樣的事情,但採用更通用的方式,以便我可以在自己的線程池中執行ProcessA和ProcessB。 – john

+0

您只能使用.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() 

將調用NO-參數構造方法,所以異常出現。

瞭解更多信息:https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

+0

以某種方式不起作用。我得到這個錯誤:'類中的方法newInstance()<捕獲#1的?擴展Process>不適用於參數(String,Properties)' – john

相關問題