0

So the basic scenario is I have a class that starts/stops service objects with the methods start(String serviceid)/stop(String serviceid). It is designed to then forward various execution tasks to the appropriate service.

What I am trying to achieve is for the start/stop methods to be non-blocking. Hence if you start you may stop immediately afterwards.

However your services may not have been initialised yet if you try to stop them after you request a start - so you want to cancel the startup process reliably. I also have methods to start/stop all defined services. The startup of a service is also bound to a timeout parameter so if it fails to start in that time it is again stopped.

Currently I have an implementation mostly based around the Executor classes. When starting a new initialisation task is created in a single thread executor. Within this is another timeout single thread executor. The initialisation task is submitted there. So in essence:

Runnable failedTask;
Runnable initialisedTask;
Callable<Exception> serviceInitialisationTask;
ExecutorService initialisationExecutor = Executors.newSingleThreadExecutor();
ExecutorService timeoutExecutor = Executors.newSingleThreadExecutor();
timeoutExecutor.execute(() -> {
    Future<Exception> future = initialisationExecutor.submit(serviceInitialisationTask);
    Exception futureException;
    try {
        futureException = future.get(timeout, timeunit);
    } catch (Exception e) {
        futureException = e;
    } finally {
        initialisationExecutor.shutdownNow();
    }
    // Call back to the class that started the service initialisation
    // This tells it whether or not the task failed and take action
    if (futureException != null) {

        failedTask.run();
    } else {
        initialisedTask.run();
    }

    timeoutExecutor.shutdownNow();
});

The initialisation task essentially creates a thread pool for the Service to execute tasks on. Failure attempts to use the same stop method as called externally. A concurrent map stores references to the servers by id. Sometimes the thread pools for the Service remain - presumably because the new service was created before the reference to the old one was used.

If that is clear does anyone know of anything that uses this sort of pattern? I have not been able to find anything that matches this but I cannot be the first person to attempt a system like this. I'm not tied to any particular way of doing this - the only thing I would like is to not have to block starting and stopping to the caller.

1

Assuming your initialization is not doing anything irreversible, what it seems to me that we're talking about is a two-phase asynchronous task.

When you start the service, you immediately launch the first phase of initialization which is itself an asynchronous task. If you decide to cancel, you should set a volatile boolean to false and simply let the initialization finish (I assume the initialization itself is not going to take a long time).

At that point, you check the status of the boolean and if false, then you abort the second phase. If you want to have more "time" to abort the second phase, then you simply make the thread sleep should it take less than a certain amount of time to finish (otherwise the asynchronous initialization may very well finish before you can tell it to stop).

I think you're needlessly complicating things as you've done it here.

  • Yes it's the "needlessly complicated" portion I'm trying to deal with.The initialisation may take a long time though - which is why I started looking at doing this in the first place with the timeout backstop when I had an occasion that there was a problem that blocked everything. – cyborg Jan 17 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.