ServiceManager类:

     用于监控服务集的管理器,该类提供了诸如startAsync、stopAsync、servicesByState方法来运行、结束和检查服务集,而且,通过监听器机制还能监控状态的改变。
     建议通过此类来管理服务的生命周期,状态转变则通过其它机制来执行。例如,如果服务集通过除startAsync之外的某些机制启动,那么监听器将在合适的时候被唤醒,同时awaitHealthy 也仍将按预期工作。
      
 
 
服务生命周期State
NEW
服务在这个状态下是不活跃的,它的作用和消耗的资源都非常小
STARTING
服务在这个状态过渡到RUNNING
RUNNING
服务在这个状态下运作
STOPPING
服务在这个状态过渡到RUNNING
TERMINATED
服务在这个状态下,说明已正常执行
FAILED
服务遇到问题,已无法启动或终止
 
 
ServiceManager主要方法
void addListener(Listener listener, Executor executor)
在executor上注册一个监听器
ServiceManager startAsync()
启动所有被管理的服务,只有当所有服务的状态为NEW时,调用此方法才不会抛异常
void awaitHealthy()
等待服务管理器变得healthy(所有服务的状态都为RUNNING )
void awaitHealthy(long timeout, TimeUnit unit)
在一定时间内,等待服务管理器变得healthy(所有服务的状态都为RUNNING )
ServiceManager stopAsync()
stop()所有管理的服务

void awaitStopped()等待所有服务都到达终止状态(所有服务的状态应该为TERMINATED或FAILED)

void awaitStopped(long timeout, TimeUnit unit)
在一定时间内,等待所有服务都到达终止状态
boolean isHealthy()

如果所有服务的状态为RUNNING,则返回true

ImmutableMultimap<State, Service> servicesByState()

获取所有服务的当前状态的快照

ImmutableMap<Service, Long> startupTimes()

返回完成启动的服务的加载时间

 
 
ServiceManager的构建——
    1)创建一个ServiceManagerState;
    2)创建一个Executor ;
    3)根据每一个Service及ServiceManagerState创建相应的ServiceListener;
    4)将每一个ServiceListener注册到Executor 上,此时会调用到每个Service的addListener方法;
    5)为services 添加Service与ServiceListener的键值对。
 
几个主要函数:
  启动所有服务:

  public ServiceManager startAsync() {
    //验证所有服务的初始状态是否为NEW。
    for (Map.Entry<Service, ServiceListener> entry : services.entrySet()) {
      Service service = entry.getKey();
      State state = service.state();
      checkState(state == State.NEW, "Service %s is %s, cannot start it.", service, 
          state);
    }
    //执行所有服务的start方法。
    for (ServiceListener service : services.values()) {
      service.start();
    }
    return this;
  }

  终止所有服务:
  public ServiceManager stopAsync() {
    for (Service service : services.keySet()) {
      service.stop();
    }
    return this;
  }
在重写start方法时,可以做一些初始化工作,返回结果为ListenableFuture<State>,调用其get方法时,将在该服务启动后,获得其状态变量(RUNNING,STOPPING或TERMINATED),如果服务启动失败,get方法将抛出ExecutionException异常,同时服务状态将为FAILED。
在重写stop方法时,返回结果也为ListenableFuture<State>,调用其get方法时,将在该服务结束后,获得其状态变量TERMINATED或抛出ExecutionException异常。

 

 
 
ServiceManagerState类——ServiceManager的所有可变状态的封装体。
 
         
ServiceManagerState主要方法
void serviceFinishedStarting(Service service, boolean currentlyHealthy)
在服务完成启动时调用
void serviceTerminated(Service service)
在服务TERMINATED时调用
void serviceFailed(final Service service)
在服务FAILED时调用
void serviceStopped(Service service)
在服务TERMINATED或FAILED时调用
void executeListeners()
执行queuedListeners中所有的监听器
void addListener(Listener listener, Executor executor)
同上
void awaitHealthy()
同上

boolean awaitHealthy(long timeout, TimeUnit unit)
同上

void awaitStopped()
同上
boolean awaitStopped(long timeout, TimeUnit unit)
同上
 
ServiceManager中的方式实际调用的即为以上方法。
 
 主要成员变量:
1)记录了服务总数(numberOfServices),未启动服务数(unstartedServices)及未终止服务数(unstoppedServices),初始值都为服务总数。
这些状态的作用体现在两个地方:
① 等待所有服务处于健康状态,涉及的条件awaitHealthGuard为:所有服务都已经启动 或 部分服务已终止。
            该条件应用在,等待所有服务处于健康状态的主体函数中:
     
    public void awaitHealthy() {

                    state.awaitHealthy();
                    checkState(isHealthy(), "Expected to be healthy after starting");
              }

        主要分两部分:
        首先在state.awaitHealthy()中,通过下面函数,等待所有服务都启动
        
private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {

             //所有服务都已启动 或 部分服务已终止,则直接返回,无需等待;

              if (!guard.isSatisfied()) {
                  if (signalBeforeWaiting) {
                        signalConditionsOfSatisfiedGuards(null);
                  }
                  incrementWaiters(guard);
                  try {
                        final Condition condition = guard.condition;
                        do {
                              condition.awaitUninterruptibly();
                        } while (!guard.isSatisfied());//若存在未启动的服务,且没有全部终止,则继续等待;
                  } finally {
                        decrementWaiters(guard);
                  }
            }
      }

              接着通过isHealthy()函数,判断所有服务处在RUNNING状态。


 ② 判断所有服务是否处于终止状态,需要满足的条件stoppedGuard即为:未终止服务数等于0。

2)Queue<Runnable> queuedListeners队列保存等待执行的监听器,调用executeListeners()时,会依次将队列中的所有方法执行并移除。

 
3)List<ListenerExecutorPair> listeners 保存了在状态转变时,需要通知的监听器,应用:
            ① serviceStopped方法被调用时,unstoppedServices减一,添加listeners中的所有监听器的stopped方法至queuedListeners队列。
            ② serviceTerminated方法被调用时,实际调用serviceStopped方法。
            ③ serviceFailed方法被调用时,添加listeners中的所有监听器的failure方法至queuedListeners队列,并调用serviceStopped方法。
            ④ serviceFinishedStarting方法被调用时,unstartedServices减1,如果参数currentlyHealthy为真,且所有服务都已启动且没终止,添加listeners中的所有监听器的 healthy方法至queuedListeners队列。
添加方法都如下:
     
  
for (final ListenerExecutorPair pair : listeners) {

          queuedListeners.add(new Runnable() {
            @Override public void run() {
              pair.execute(new Runnable() {
                @Override public void run() {
                  pair.listener.stopped();
                }
              });
            }
          });
        }

  
 
ServiceListener类:

封装了另一种服务及其启动时间,同时会根据当前状态调用ServiceManagerState的serviceFinishedStarting ,serviceTerminated ,serviceFailed 方法。

 
 

DEMO:
下面从终止服务为例,说下Service及ServiceManager的监听器,也不知道自己这样用对不对....
我们可以在实现Service接口的类中,重写addListener方法,该方法将在构造服务管理器时,被调用:
调用处:

ServiceListener listener = new ServiceListener(service, state);
       service.
addListener(listener, executor);

 
重写的addListener方法:
    @Override
      public void addListener(Listener listener, Executor executor) {
           this.listener =
 
listener;
           System.out.println(serviceInfo+"注册监听器");
      }

 
接着重写stop方法,当服务管理器执行stopAsync() 方法时,将依次执行每个服务的stop方法:
    @Override
    public ListenableFuture<State> stop() {
       
 
listener.
terminated(state);
        System.out.println(serviceInfo + "终止...");
        return null;
    }

 
此处我们调用listener的terminated方法:
    
@Override public void terminated(State from) {
          logger.info("Service " + service + " has terminated. Previous state was " + from + " state.");
          state.monitor.enter();
          try {
                if (from == State.NEW) {
                      startTimer();
                      finishedStarting(false);
                }
                state.serviceTerminated(service);
          } finally {
                state.monitor.leave();
                state.executeListeners();
          }
    }

 
serviceTerminated方法实际调用的为serviceStopped方法,在该方法中将unstoppedServices(未终止服务数)减一,若所有服务都已终止,则将listeners中所有监听器的stopped方法加入queuedListeners队列中稍后执行。
    
private void serviceStopped(Service service) {
          checkState(unstoppedServices > 0, "All services should have already stopped but %s just stopped.", service);
          unstoppedServices--;
          if (unstoppedServices == 0) {
                checkState(unstartedServices == 0, "All services are stopped but %d services haven't finished starting",  unstartedServices);
                for (final
 
ListenerExecutorPair pair : listeners) {
                      queuedListeners.add(new Runnable() {
                            @Override public void run() {
                                    pair.execute(new Runnable() {
                                        @Override public void run() {
                                              pair.listener.stopped();
                                        }
                                  });
                            }
                      });
                    }
              listeners.clear();
          }
    }

 

listeners中的监听器,是通过服务管理器的addListener方法(Service也有addListener方法)添加的,在该方法中会将监听器添加到listeners队列中,当服务状态发生改变时,通知队列中的监听器。

这些监听器除了有stopped方法,还有healthy及failure方法,通过这几个方法,我们可以监视所有服务的运行状态,在下面的例子中,我们可以看到运行结果中出现"服务运行结束!"字样,说明已检测到所有服务都运行结束。

 

ServiceImp实现类:
public class ServiceImp implements Service {
    private State state = NEW;
    private String serviceInfo;
    private Listener listener;
 
    ServiceImp(int num){
        this.serviceInfo = "第"+num+"个任务:";
    }
    @Override
    public ListenableFuture<State> start() {
        System.out.println(serviceInfo+"启动...");
        listener.starting();
        return null;
    }
    @Override
    public State startAndWait() {
        return state;
    }
    @Override
    public boolean isRunning() {
        if(state== RUNNING)
            return true;
        else
            return false;
    }
    @Override
    public State state() {
        return state;
    }
    @Override
    public ListenableFuture<State> stop() {
        listener.
terminated(state);
        System.out.println(serviceInfo + "终止...");
        return null;
    }
    @Override
    public State stopAndWait() {
        return state;
    }
    @Override
    public Throwable failureCause() {
        return null;
    }
    @Override
    public void addListener(Listener listener, Executor executor) {
        this.listener =
 
listener;
        System.out.println(serviceInfo+"注册监听器");
    }
}

运行服务:

public class Server {
    public static void main(String[] args) {
        List<Service> services = Lists.newArrayList();
        for (int num = 0; num < 5; num++) {
            ServiceImp serviceImp = new ServiceImp(num);
            services.add(serviceImp);
        }
        System.out.println("*******构造服务管理器*******");
 
        final ServiceManager serviceManager = new ServiceManager(services);
        serviceManager.
addListener(new ServiceManager.Listener() {
            @Override
            public void healthy() {
                System.out.println("服务运行健康!");
            }
            @Override
            public void stopped() {
                System.out.println("服务运行结束!");
            }
            @Override
            public void failure(Service service) {
                System.out.println("服务运行失败!");
            }
        }, MoreExecutors.sameThreadExecutor());
 
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                try {
                    System.out.println("********终止所有任务********");
                    serviceManager.stopAsync().awaitStopped(10, TimeUnit.SECONDS);
                } catch (Exception timeout) {
                    System.out.println("timeout");
                }
            }
        });
 
        System.out.println("********启动所有任务********");
        serviceManager.startAsync();
 
    }
}


运行结果:
*******构造服务管理器*******
第0个任务:注册监听器
第1个任务:注册监听器
第2个任务:注册监听器
第3个任务:注册监听器
第4个任务:注册监听器
********启动所有任务********
第0个任务:启动...
第1个任务:启动...
第2个任务:启动...
第3个任务:启动...
第4个任务:启动...
********终止所有任务********
第0个任务:终止...
第1个任务:终止...
第2个任务:终止...
第3个任务:终止...
服务运行终止!
第4个任务:终止...

Guava源码分析——ServiceManager的更多相关文章

  1. Guava 源码分析(Cache 原理 对象引用、事件回调)

    前言 在上文「Guava 源码分析(Cache 原理)」中分析了 Guava Cache 的相关原理. 文末提到了回收机制.移除时间通知等内容,许多朋友也挺感兴趣,这次就这两个内容再来分析分析. 在开 ...

  2. Guava 源码分析之Cache的实现原理

    Guava 源码分析之Cache的实现原理 前言 Google 出的 Guava 是 Java 核心增强的库,应用非常广泛. 我平时用的也挺频繁,这次就借助日常使用的 Cache 组件来看看 Goog ...

  3. [Guava源码分析]ImmutableCollection:不可变集合

    摘要: 我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3888557.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的 ...

  4. [Guava源码分析]Ordering:排序

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3876466.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  5. Guava 源码分析(Cache 原理)

    前言 Google 出的 Guava 是 Java 核心增强的库,应用非常广泛. 我平时用的也挺频繁,这次就借助日常使用的 Cache 组件来看看 Google 大牛们是如何设计的. 缓存 本次主要讨 ...

  6. Guava 源码分析之 Beta, GwtCompatible, GwtIncompatible, Charset, HashCode

    com.google.common.annotations.Beta /** * 表明一个公用API的未来版本是受不兼容变更或删除限制的 * 拥有这个注释标志的API不受任何兼容性保证 * */ @R ...

  7. [Guava源码分析]Objects 和 ComparisonChain:帮助重写Object方法

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3874194.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  8. [Guava源码分析] Preconditions 前置条件

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3874170.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  9. Guava cacha 机制及源码分析

    1.ehcahce 什么时候用比较好:2.问题:当有个消息的key不在guava里面的话,如果大量的消息过来,会同时请求数据库吗?还是只有一个请求数据库,其他的等待第一个把数据从DB加载到Guava中 ...

随机推荐

  1. Kerberos-KDC

    Kerberos提供一种较好的解决方案,它是由MIT发明的,Kerberos建立了一个安全的.可信任的密钥分发中心(KDC, Key Distribution Center).Kerberos是一种认 ...

  2. WebAPI中Message Handler与Filter的区别

    两者最主要的区别是关注点不同.Message Handlers应用到HTTP Request,Filters仅应用到controller/action上. 如果某种行为应用到大多数的Request时, ...

  3. 学习MVC框架之一

    一.MVC的概述 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑和数据显示分离的 ...

  4. cocos2dx 碰撞检测

    //必须 要有float类型的参数 void MainScene::updateFrame(float dt) { if (spriteTest != NULL && spriteTe ...

  5. unity 之2D游戏简单操作

    unity 做2D项目也很方便.  首先要调整camera的模式,camera 的检视面板参数如下: perspective 模式就是平时用的 模式.摄像机到游戏物体是有角度的张开, 而 orthog ...

  6. C++格式化字符函数

    格式化有很多种方法,啊,1,sprintf函数可以实现格式化字符串,并保存到一个字符数组2,snprintf也能实现但比起sprintf函数稍微要安全一些了啊3,ostringstream对象也能实现 ...

  7. CentOS和Ubuntu的区别

    CentOS(Community ENTerprise Operating System)是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定释出的源代 ...

  8. [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  9. 5W1H分析法

    "5W1H分析法"也叫"六何分析法",它是一种分析方法也可以说是一种创造技法.是对选定的项目.工序和操作,都要从原因(Why).对象(What).地点(Wher ...

  10. HttpAsyncClient 的简单使用

    下载地址:http://hc.apache.org/downloads.cgi 在NetBeans中导入以下jar文件: 1:一次请求: public static void oneReuest(){ ...