Come progettare il sistema che esegue due processi in modo indipendente con una configurazione diversa?

1

Ho due process ProcessA e ProcessB . Voglio eseguire questi due processi indipendentemente l'uno dall'altro. Non esiste alcuna relazione tra di loro.

  • Ogni processo dovrebbe avere un diverso oggetto Proprietà.
  • Ogni processo dovrebbe avere una configurazione del pool di thread diversa poiché possono essere eseguiti in modalità multithread se necessario indipendentemente da altri processi.

Di seguito è riportato il mio progetto:

Classe di processo (abstract):

public abstract class Process implements Runnable {
  private final Properties props;
  private final String processName;

  public Process(String processName, Properties props) {
    this.processName = processName;
    this.props = props;
  }

  public abstract void shutdown();
}

Classe ProcessA:

public class ProcessA implements Process {

  public ProcessA(String processName, Properties props) {
    super(processName, props);
  }

  @Override
  public void run() {
    // add run code here
    // all the logic of executing my process comes here
    // here it uses "processName" and "props" object to do certain things
  }

  @Override
  public void shutdown() {
    // shut down code
  }
}

Classe processo B:

// similar to 'ProcessA' but with specific details of B

Classe ProcessHandler (abstract):

public abstract class ProcessHandler {
  private final ExecutorService executorServiceProcess;
  private final List<Process> processList;
  private final int poolSize;

  protected ProcessHandler(int poolSize) {
    this.executorServiceProcess = Executors.newFixedThreadPool(poolSize);
    this.processList = new ArrayList<>();
    this.poolSize = poolSize;
  }

  public void postInit(Process process) {
    for (int i = 0; i < poolSize; i++) {
      processList.add(process);
      executorServiceProcess.submit(process);
    }
  }

  public void shutdown() {
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        for (Process process : processList) {
          process.shutdown();
        }
        executorServiceProcess.shutdown();
        try {
          executorServiceProcess.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ex) {
          Thread.currentThread().interrupt();
        }
      }
    });
  }
}

Classe ProcessHandlerA:

public class ProcessHandlerA extends ProcessHandler {

  public ProcessHandlerA() {
    super(3);// configure pool size properly w.r.to ProcessA
  }

  public void postInit() {
    ProcessA processA = new ProcessA("processA", properties);
    super(processA);
  }

  public void shutdown() {
    super.shutdown();
  }
}

Classe ProcessHandlerB:

// similar to ProcessHandlerA but with specific details for B

Di seguito è la mia classe principale in uno dei miei progetti in cui eseguo il mio ProcessA e ProcessB .

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Singleton;

@Singleton
@DependencyInjectionInitializer
public class Initializer {

  @Inject
  private ProcessHandlerA processHandlerA;

  @Inject
  private ProcessHandlerB processHandlerB;

  @PostConstruct
  public void init() {
    processHandlerA.postInit();
    ProcessHandlerB.postInit();
  }

  @PreDestroy
  public void shutdown() {
    processHandlerB.shutdown();
    processHandlerB.shutdown();
  }
}

E in qualche altro progetto la mia classe principale sarà:

public class Initializer {

  public static void main(String[] args) {
    // call both processes from here
  }
}

È questo il progetto giusto per questo tipo di problema? Fammi sapere se esiste un modo migliore ed efficace per risolvere questo problema.

    
posta david 28.11.2016 - 01:46
fonte

1 risposta

1

Questa domanda è più adatta per la revisione del codice.

La tua soluzione va bene, ma usi l'ereditarietà e il DI. Aggiungendo un argomento del costruttore del processo a ProcessHandler e rimuovendo il metodo postInit, rendere ProcessHandler permanentemente coerente e impedire la necessità di estenderlo per ogni nuovo processo.

public final class ProcessHandler {
  private final ExecutorService executorServiceProcess;
  private final Process process;

  public ProcessHandler(Process process, int poolSize) {
    this.executorServiceProcess = Executors.newFixedThreadPool(poolSize);
    this.process = process;
    for (int i = 0; i < poolSize; i++) {
      executorServiceProcess.submit(process);
    }
 }
  public void shutdown() {
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        executorServiceProcess.shutdown();
        process.shutdown ();
        try {
          executorServiceProcess.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ex) {
          Thread.currentThread().interrupt();
        }
      }
    });
  }
}

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Singleton;

@Singleton
@DependencyInjectionInitializer
public class Initializer {

  // Use named injections, optionally
  private final ProcessHandler processHandlerA = new ProcessHandler (new ProcessA(), 3);
  private final ProcessHandler processHandlerB = new ProcessHandler (new ProcessB(), 3);

  @PreDestroy
  public void shutdown() {
    processHandlerB.shutdown();
    processHandlerB.shutdown();
  }
}
    
risposta data 28.11.2016 - 02:49
fonte