Guava的Service

Guava的Service

一、Guava的Service介绍

Guava的Service接口代表一个对象拥有操作状态,带有从开始到结束的方法。例如,web服务、RPC服务、计时器等能够实现Service接口。管理此类服务的状态,它们需要恰当的启动和停止管理,它们很重要,尤其是设计多线程调度。Guava 提供了一些骨架来为您管理状态逻辑和同步细节。

二、使用Service

一个正常Service的生命周期:

  • Service.State.NEW
  • Service.State.STARTING
  • Service.State.RUNNING
  • Service.State.STOPPING
  • Service.State.TERMINATED

一个已经停止的服务不能重新运行。如果服务在启动(starting)、运行(running)或停止(stopping)的时候失败,它将进入Service.State.FAILED状态。

如果NEW状态的服务,可以通过startAsync()以异步的方式启动。因此,您应该构建您的应用程序,使其具有启动每个服务的唯一位置。

停止服务是类似的,使用异步的stopAsync()方法。但与startAsync() 方法不同,可以安全的调用该方法多次。这是为了处理关闭服务会发生的竞争。

Serevice也提供了一些方法等待服务的转换完成:

  • 异步使用addListener() 。它允许你添加Service.Listener,它将会在每次状态转换的时候进行调用。注: 如果在添加侦听器时服务不是 NEW,则任何已经发生的状态转换都不会在侦听器上重播。
  • 同步使用awaitRunning()。这是不间断的,不抛出任何检查异常,并在服务完成启动后返回。如果服务无法启动,则会引发 IllegalStateException。类似的,awaitTerminated()等待服务达到终止状态(TERMINATED或FAILED)。这两种方法还具有允许指定超时的重载。

Service 接口是微妙的、复杂的。我们不推荐直接实现它。相反请使用抽象的基础类作为它的实现。每个基础类都支持特定的线程模型。

三、实现

3.1 AbstractIdleService

那个AbstractIdleService骨架实现了Service。在“running”状态下不需要做任何事情。因此,在运行的不需要线程——除了执行启动和关闭操作。实现这样的服务就像扩展 AbstractIdleService 并实现 startUp() 和 shutDown() 方法一样简单。

3.2 AbstractExecutionThreadService

一个 AbstractExecutionThreadService 执行启动、运行、停止行为在单个线程中。你必须覆盖run()方法。它必须响应停止请求。

覆盖 startUp() 和 shutDown() 是可选的,但将为您管理服务状态。

请注意,start() 调用您的 startUp() 方法,为您创建一个线程,并在该线程中调用 run()。 stop() 调用 triggerShutdown() 并等待线程终止。

3.3 AbstractScheduledService

一个AbstractScheduledService做一些周期性的任务。子类实现runOneIteration() 指定任务的一次迭代,以及熟悉的startUp()shutDown()方法。

为了描述执行调度,必须实现scheduler() 方法。通常你将使用由AbstractScheduledService.Scheduler提供的定时。即可以AbstractScheduledService.Scheduler.newFixedDelaySchedule(Duration initialDelay, Duration delay),也可以AbstractScheduledService.Scheduler.newFixedRateSchedule(Duration initialDelay, Duration delay)。和ScheduledExecutorService中熟悉的方法对应。

自定义Schedule可以通过实现AbstractScheduledService.CustomScheduler

3.4 AbstractService

当你需要做自己的手动线程管理的时候,直接覆盖AbstractService

为了实现AbstractService,你必须实现两个方法:

  • doStart() 由第一次调用 startAsync() 直接调用,您的 doStart() 方法应执行所有初始化,然后在启动成功时最终调用 notifyStarted() 或在启动失败时调用 notifyFailed()。
  • doStop() doStop() 由第一次调用 stopAsync() 直接调用,您的 doStop() 方法应该关闭您的服务,然后如果关闭成功则最终调用 notifyStopped() 或如果关闭失败则调用 notifyFailed()。

你的doStart()doStop()方法应该是快的。如果你要做代价比较高的初始化,比如读文件、打开网络连接,或任何其它阻塞的操作,你应该考虑将它们移到另外的线程。

四、使用ServiceManager

除了Service骨架的实现,Guava提供了ServiceManager类,使操作涉及多个Service实现更容易。创建一个带有一个集合Service的ServiceManager。然后能管理它们:

  • startAsync() 将启动管理下的所有服务。非常像Service#startAsync(),你只需要调用一次,所有的service都NEW。
  • stopAsync() 停止管理下的所有服务。
  • addListener 添加ServiceManager.Listener,当主要的状态转换的时候,监听将会调用;
  • awaitHealthy() 将等待所有的service到达RUNNING状态
  • awaitStopped() 将等待所有的service到达终止状态

或者检查它们:

  • isHealthy() 如果所有的service是RUNNING状态;
  • servicesByState() 返回按状态索引的所有服务的一致快照。
  • startupTimes() 从受管理的服务返回一个映射到该服务启动所需的时间(以毫秒为单位)。 返回的Map保证按启动时间排序。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值