多线程在Java中安全启动/停止服务实例
我正在开发一个使用LDAP服务器作为持久存储的多线程应用程序。我创建了以下服务类,用于在需要时启动和停止LDAP服务:
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?
}
}
我们目前使用Google Guice将服务实现作为单例实例注入:
public class ServiceModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides @Singleton
LdapService providesLdapService() {
return new LdapServiceImpl();
}
}
这样,我们可以在应用程序启动时设置连接池,对连接执行一些操作,然后在应用程序关闭时释放资源:
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();
}
});
}
我面临的问题是,我想确保服务只启动/停止一次。出于这个原因,我在服务实现中添加了一个“isRunning()”方法,但我不确定如何实现它
考虑到应用程序是多线程的,而我的服务实例是单实例,实现“isRunning()”方法的最佳方法是什么
此外,是否有更好/更清洁的方法来实现这一点
提前谢谢
# 1 楼答案
djmorton的答案绝对正确,无论是工作任务还是业余项目,你都可以安全地实施它
话虽如此,这里还有另一个解决方案——有些人可能会说它比安全简单的解决方案有一些优势,但我不会这么说。我添加它只是为了展示另一种方法(因为在问题上抛出代码很有趣)
# 2 楼答案
如果LdapServiceImpl是单例的,并且您担心多个线程同时调用start或stop方法,那么您应该能够简单地将synchronized关键字添加到start和stop方法中。此时,您可以只使用一个简单的布尔标志来存储当前的运行状态,只要访问该状态的所有方法都是同步的,您就应该是安全的
# 3 楼答案
由于您已经在使用google工具,您可以查看guavas servicemanagerhttp://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/ServiceManager.htmlresp。服务接口http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/Service.html