Guillermo R Guillermo R - 7 months ago 21
Java Question

Starting/Stopping a service instance safely in Java

I am working on an multi-threaded application that uses an LDAP server as the persistent storage. I have created the following service class to start and stop the LDAP service when needed:

public class LdapServiceImpl implements LdapService {

public void start() {
if (!isRunning()) {
//Initialize LDAP connection pool
}
}

public void stop() {
if (isRunning()) {
//Release LDAP resources
}
}

private boolean isRunning() {
//What should go in here?
}

}


We currently use Google Guice to inject the service implementation as a singleton instance:

public class ServiceModule extends AbstractModule {

@Override
protected void configure() {
}

@Provides @Singleton
LdapService providesLdapService() {
return new LdapServiceImpl();
}

}


That way we can set up the connection pool when the application starts, do something with the connections, and then release the resources when the application shuts down:

public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(new ServiceModule());

Service ldapService = injector.getInstance(LdapService.class));
ldapService.start();
addShutdownHook(ldapService);

//Use connections

}

private static void addShutdownHook(final LdapService service) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
service.stop();
}
});
}


The problem I am facing is that I want to make sure the service is only started/stopped once. For that reason I added an "isRunning()" method to the service implementation but I am not sure how to implement it.

What would be the best way to implement the "isRunning()" method considering that the application is multi-threaded and that my Service instance is a singleton?

Also, is there a better/cleaner way of achieving this?

Thanks in advance.

Answer

If LdapServiceImpl is a singleton, and you are worried about multiple threads calling the start or stop methods concurrently, you should be able to simply add the synchronized keyword to the start and stop methods. At that point, you can just use a simple boolean flag to store the current running state, and as long as all the methods that access that state are synchronized you should be safe.

public class LdapServiceImpl implements LdapService {

    private boolean isRunning = false;

    public synchronized void start() {
        if (!isRunning()) {
            //Initialize LDAP connection pool
            isRunning = true;
        }
    }

    public synchronized void stop() {
        if (isRunning()) {
            //Release LDAP resources
            isRunning = false;
        }
    }

    private boolean isRunning() {
        return isRunning;
    }
}