Guava文档翻译之 Service

时间:2022-02-01 22:22:21

概览

Guava的接口代表了一个有运行状态的对象,有启动和停止的方法。比如网络服务器,RPC服务器,以及计时器等,都可以实现Service接口。掌管像这样的服务的状态,需要正确地管理启动和关闭,因此会是繁琐的,特别是牵扯到多线程和调度。Guava提供了一个基本的骨架,可以帮你管理状态逻辑,以及同步的细节

一个Service的通常的生命周期是

一个已经停止的Service是不能被重启的。如果这个服务在启动或者运行、停止时失败,那么它会转入Service.State.FAILED状态。

一个服务可以被使用 startAsync()来异步地启动,这个方法会返回'this'引用,以方便地使用方法链。只有这个服务是NEW状态的时候才能调用。所以,你的程序应该有个唯一的地方来启动每一个服务。

停止服务是类似的,使用异步的stopAsync()方法。但是不像startAsync()方法,它可以安全地调用多次。这使得可以它可以应对在关闭服务器可能遇到的竞争问题。

服务也提供了几种方法来等待服务状态转换的完成。

  • 异步地使用addListener()。addListener()允许你添加一个Service.Listener,它会在服务的服务状态转换时被调用。需要注意的是,如果在这个listener被添加时,服务器已经不是NEW的状态。,那么已经发生过的状态转换是不会在这个listener上重放。
  • 异步地使用awaitRunning()。它是不可中断的(uniterruptible),不会抛出受检异常,会在服务启动完毕时返回。如果服务启动失败,会抛出一个IllegalStateException。类似的是 awaitTerminated(),调用它等待服务到达终止状态(TERMINATED or FAILED)。这两个方法都有重载的方法,允许指定超时时间。

Service接口是微妙的。我们不建议直接实现它。你可以使用我们在guava提供几个虚类中的一个作为你的实现的基础。每个基类提供了一个特定的线程模型。

实现

AbstractIdleService

AbstractIdleService骨架实现了一个Service,这个服务不需要在“running”状态执行任何动作,因此它在运行时也不需要一个线程,但是它仍然需要执行启动和停止的动作。实现这样的服务只需要继承AbstractIdleService,并且实现 startUp()以及shutDown()方法,

protected void startUp() {
servlets.add(new GcStatsServlet());
}
protected void shutDown() {}

需要指出的是,任何对GcStatsServlet的查询已经运行于一个线程中了。因此,在这个服务运行时,我们不需要它执行任务操作。

AbstractExecutionThreadService

一个AbstractExecutionThreadService在同一个线程中执行启动,动行和关闭操作。你必须重写run() 方法,而且这个方法必须对关闭请求作为响应。比如,你或许会在一个工作循环中执行这些动作:

public void run() {
while (isRunning()) {
// perform a unit of work
}
}

或者,你可以覆盖 triggerShutdown()方法,只要它能够使得run()方法返回。覆盖startUp()和shutdown()方法是可选的,但是服务的状态会由这个骨架替你管理。

protected void startUp() {
dispatcher.listenForConnections(port, queue);
}
protected void run() {
Connection connection;
while ((connection = queue.take() != POISON)) {
process(connection);
}
}
protected void triggerShutdown() {
dispatcher.stopListeningForConnections(queue);
queue.put(POISON);
}

需要注意的是start()调用了你的startUp()方法,为你创建了一个线程,并且在这个线程中调用run()方法。stop()方法调用了triggerShutdown()方法,并且等待线程停止。(译注:重点是run()方法不是在调用start()的线程中执行的)

AbstractScheduledService

一个AbstractScheduledService在它动行时执行一些周期性的任务。它的子类覆盖runOneIteration()来指定每个周期的任务,同时也需要覆盖我们熟悉的startUp和shutDown() 方法

为了描述怎么调度执行,你需要实现scheduler()方法。通常而言,你会使用已经AbstractScheduledService.Scheduler提供的几个调度器中的一个,newFixedRateSchedule(initialDelay, delay, TimeUnit)或者newFixedDelaySchedule(initialDelay, delay, TimeUnit),与我们熟知的ScheduledExecutorService中的方法相类。自定义的调度器可以用来实现,请参见Javadoc.

AbstractService

如果你需要自己管理线程,就需要直接覆盖AbstractService。通常来说,以上提到的几种实现就够用了,但是,有些情况下是建议实现AbstractService的,比如,你对有自己的线程语义的东西进行建模,把它做成一个Service,你就会有自己特殊的线程相关的需求。

为了实现AbstractService,你需要实现这两个方法

  • doStart():doStart()在第一次调用startAsync()时被直接调用,你的doStart()方法应该完成所有初始化工作,并且在启动成功时调用,或者启动失败时调用。
  • doStop():doStop()在第一次调用stopAsync()时被调用,你的doStop()方法应该关闭你的服务,并且如果关闭成功,最终调用notifyStopped(),或者关闭失败,就调用notifyFailed()

你的doStart和doStop方法应该执行得很快。如果你需要进行昂贵的初始化工作,比如读取文件,开启网络连接,或者进行任何可能会阻塞的工作,你需要移动这些工作到另一个线程去做。

使用SerivceManager

在Service的骨架实现之外,Guava还提供了一个ServiceManager类,它使得一些跟多个Service的实现相关操作操作更简单一些。使用Service的集合创建一个新的ServiceManager。然后你就可以管理它们了:

或者检查这些服务:

  • isHealthy() 在所有服务都在状态时返回true
  • 将会返回一个所有服务的一致的snapshot,以它们的状态作为索引。
  • startupTimes()将会返回从受管理的Service到它花了多少毫秒启动的map.Guava保证这个返回的map将按照启动时间(startup time)排序。

别然我们建议服务的生命周期通过ServiceManager来管理,但是通过其它机制进行的状态转换不会影响它的方法的正确性。比如,如果一些服务不是通过startAsync()启动的,监听器仍然会在合适的时机被调用,并且 awaitHealthy()也会照常工作。ServiceManager的唯一要求是在ServiceManager构造时,所有的Serivce都在NEW状态。

Guava文档翻译之 Service的更多相关文章

  1. Guava文档翻译之 Guava简介

    用户指南 User Guide Guava项目包括了一些Google的核心库,是我们在基于Java的项目中所依赖的,这些库包括:集合,缓存,对基本类型的支持,并发库,通用的注解,字符串处理,I/O,等 ...

  2. Guava文档翻译之ListenableFuture

    ListenableFutureExplained 并发是一个困难的问题,但是使用强大而简单的抽象可以极大地简化并发问题.为了简化事情,Guava使用ListenableFuture继承了JDK的Fu ...

  3. [Guava官方文档翻译] 1.Guava简介 (Introduction)

    用户指南 Guava包含Google在Java项目中用到的一些核心库:collections, caching, primitives support, concurrency 库, common a ...

  4. [Guava官方文档翻译] 7. Guava的Immutable Collection(不可变集合)工具 (Immutable Collections Explained)

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

  5. [Guava官方文档翻译] 6. 用Guava辅助Throwable异常处理 (Throwables Explained)

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

  6. [Guava官方文档翻译] 5. Guava的Object公共方法 (Common Object Utilities Explained)

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

  7. [Guava官方文档翻译] 4. 使用Guava Ordering排序 (Ordering Explained)

    本文地址:http://www.cnblogs.com/hamhog/p/3537233.html 示例 assertTrue(byLengthOrdering.reverse().isOrdered ...

  8. [Guava官方文档翻译] 3. 前置条件检查(Preconditions Explained)

    本文地址:http://www.cnblogs.com/hamhog/p/3536964.html 前置条件检查 Guava提供了一些检查前置条件的utilities.我们强烈建议静态import这些 ...

  9. [Guava官方文档翻译] 2.使用和避免使用null (Using And Avoiding Null Explained)

    本文地址:http://www.cnblogs.com/hamhog/p/3536647.html "null很恶心." -Doug Lea "这是一个令我追悔莫及的错误 ...

随机推荐

  1. jq随手写图片放大

    html: <img id="img1" src="<?php echo $info->business_licence_img; ?>&quot ...

  2. UITableViewCell重用导致内容混乱方案

    UITableViewCell *cell=nil; static NSString *reuse=@"cell"; if (cell==nil) { cell=[[UITable ...

  3. 查看linux中swap内存的相关参数

    内容主要来源于:linux的内存回收和交换 各项命令查看的linux环境是:Linux SUSE-33 2.6.32.12-0.7-defaul zone? 内存管理的相关逻辑都是以zone为单位的, ...

  4. 解决 React-Native mac 运行报错 error Failed to build iOS project&period; We ran &quot&semi;xcodebuild&quot&semi; command but it exited with error code 65&period; To debug build logs further&comma; consider building your app with Xcode&period;app&comma; by ope

    React-Native 开发的项目,Android 方面没有任何问题,IOS 就是无法跑起来,报错信息如下: mac 10.14.4 xcode 10.2.1 error Failed to bui ...

  5. 2018-2019-2-20175235 实验一 《Java开发环境的熟悉》实验报告

    实验一 Java开发环境的熟悉 实验内容及要求: 1.使用JDK编写简单的Java程序 2.使用IDEA编辑编译运行调试测试Java程序 实验内容,步骤与心得: (一).Linux命令行下Java程序 ...

  6. 活字格对接RF手持机与ERP系统,帮助RFID快速盘点方案落地

    这个玩意有点意思,要不要搞来玩玩? ----------- 射频技术(RF)是Radio Frequency的缩写,较常见的应用有无线射频识别(Radio Frequency Identificati ...

  7. Vertica系列&colon;从一些细节看Vertica为什么是一个优秀的数据仓库平台

    ===========================================对象名称可以长到128字符===========================================1 ...

  8. 四、UI开发之核心基础——约束(实用)

    概述 本节将会介绍最常用的几种约束,基本可以满足90%以上的UI布局要求. 先附上一份其他优秀博客https://blog.csdn.net/companion_1314/article/detail ...

  9. LeetCode——300&period; Longest Increasing Subsequence

    一.题目链接:https://leetcode.com/problems/longest-increasing-subsequence/ 二.题目大意: 给定一个没有排序的数组,要求从该数组中找到一个 ...

  10. postgresql的启停和创建

    一.启停方法 两种方法 1.直接运行postgres进程启动: 2.使用pg_ctl命令启动 postgres -D /home/osdba/pgdata  & 二.停止数据库的三种模式 sm ...