Global control for Executorservice

Asked

Viewed 142 times

0

I run a software locally in Java SE, basically it is the synoptic of a equipment in the field, can be controlled by this software. The user has several functions within it, being able to call, change status, settings, etc.

Each function is executed by a separate thread, so as not to compromise the UI. I would like to centralize the creation of these command threads by creating a class global that would return the Executorservice

It is worth turning this into "global" scope within my application, or working with the Executors separated by command would be the most correct?

Example of a global class of ExecutorService(basic):

    class GlobalThreadPool {

      int maximumPoolSize = 4;

      final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Orders-%d").setDaemon(true).build();

      final ExecutorService executorService = Executors.newFixedThreadPool(maximumPoolSize, threadFactory);

    }

1 answer

2


If the program has several different interactions with threads, it makes sense to center and encapsulate this functionality in a specialized class.

On the name, I would avoid anything named "global" and in this case exposing implementation details.

A priori, I would model this class first by defining interfaces for the manager running the program functions and for the commands. Example:

interface Comando {
    void executar();
}

interface GerenciadorExecucao {
    void executar(Comando c);
}

Note that the interfaces do not say how the commands will be executed. Such detail will be managed by the implementation and the other classes have nothing to do with it, for them this is transparent, they just expect the command to be executed.

As for the implementation, I would create a class called GerenciadorExecucaoAssincrono containing a thread pool whose threads consume the commands of a synchronized queue as 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);
    }
}

You can now create any command implementation in other classes. This way, every feature of your system can use the new asynchronous and uncoupled execution API.

In the above example, I created a single thread consuming the commands, so the result is that the commands are executed in the same order they are added to the queue.

However, you can have multiple threads and run them in parallel, just submit several times the same Runnable I put in the lambda above. The problem with this is that the 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.

  • 1

    Thank you very much for the answer. I understood your placement perfectly, really this way I can leave the commands uncoupled. Some equipment use TCP/IP others use Serial for communication, by several factors, that way I could not use them in parallel, because I would only have an equal exit door. I will still have to think of something as a priority for these commands, but this is for a next question, after I try to implement some logic for this. Thanks again.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.