If the program has several different interactions with threads, it makes sense to centralize and encapsulate this functionality in a specialized class.
On the name, I would avoid anything with a "global" name and, in this case, setting out implementation details.
A priori, I would model this class first by defining interfaces for the manager that performs the functions of the program and for the commands. Example:
interface Comando {
void executar();
}
interface GerenciadorExecucao {
void executar(Comando c);
}
Note that interfaces do not tell you how commands will run. This detail will be managed by the implementation and the other classes have nothing to do with it, for them this is transparent, they just wait for the command to execute.
Regarding the implementation, I would create a class called GerenciadorExecucaoAssincrono
containing a thread pool whose threads consume the commands of a synchronized queue like LinkedBlockingQueue
. Example;
class GerenciadorExecucaoAssincrono implements GerenciadorExecucao {
private final int maximumPoolSize = 4;
private final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Orders-%d").setDaemon(true).build();
private final ExecutorService executorService = Executors.newFixedThreadPool(maximumPoolSize, threadFactory);
private final LinkedBlockingQueue<Comando> queue = new LinkedBlockingQueue<>()
public GerenciadorExecucaoAssincrono() {
//thread que fica em loop infinito consumindo os comandos da fila
executorService.submit(() -> {
while(true) {
Comando c = queue.take(); //espera por um comando na fila
c.executar();
}
});
}
public void executar(Comando c) {
//adiciona o comando à fila, desbloqueando a thread acima
queue.put(c);
}
}
Now you can create any command implementation in other classes. In this way, each functionality of your system can use the new asynchronous execution API and decoupled.
In the example above, I created a single thread consuming the commands, so the result is that the commands are executed in the same order as they are added to the queue.
However, you can have multiple threads and run them in parallel, just submit several times the same Runnable
that I put in the lambda above. The problem with this is that commands executed at the same time could have an unwanted effect, since you have physical equipment and possible limitations. It's up to you to analyze this and think about the best strategy.