当前位置: 首页 > news >正文

做图片推广的网站/产品推广策划

做图片推广的网站,产品推广策划,学做蛋糕什么网站,宝安石岩网站建设一个设计优秀的工具或框架,应该都有一个易用、强大的插件或扩展体系,akka也不例外。 akka的扩展方法非常简单,因为只涉及到两个组件:Extension、 ExtensionId。其中Extension在每个ActorSystem中只会加载一次,然后被ak…

  一个设计优秀的工具或框架,应该都有一个易用、强大的插件或扩展体系,akka也不例外。

  akka的扩展方法非常简单,因为只涉及到两个组件:Extension、 ExtensionId。其中Extension在每个ActorSystem中只会加载一次,然后被akka管理。你可以在ActorSystem启动的时候以编程的方式加载,也可以通过配置的方式自动加载。由于Extension是在ActorSystem层面的扩展,所以需要开发者自己处理线程安全的问题。ExtensionId可以理解为Extension的一个唯一标志,ActorSystem会根据它来判断Extension是否被加载过,以确保Extension只能加载一次。

/*** The basic ActorSystem covers all that is needed for locally running actors,* using futures and so on. In addition, more features can hook into it and* thus become visible to actors et al by registering themselves as extensions.* This is accomplished by providing an extension—which is an object* implementing this trait—to `ActorSystem.registerExtension(...)` or by* specifying the corresponding option in the configuration passed to* ActorSystem, which will then instantiate (without arguments) each FQCN and* register the result.** The extension itself can be created in any way desired and has full access* to the ActorSystem implementation.** This trait is only a marker interface to signify an Akka Extension. */
trait Extension

   上面是Extension的定义,可以看出它非常简单,简单到就是一个trait,没有任何字段和方法。也就是说我们实现的对akka的扩展可以是任意形式的类,而且会被保证加载一次,那么是如何保证只会加载一次的呢?ExtensionId也许可以回答这个问题。

/*** Identifies an Extension* Lookup of Extensions is done by object identity, so the Id must be the same wherever it's used,* otherwise you'll get the same extension loaded multiple times.*/
trait ExtensionId[T <: Extension] {/*** Returns an instance of the extension identified by this ExtensionId instance.*/def apply(system: ActorSystem): T = {java.util.Objects.requireNonNull(system, "system must not be null!").registerExtension(this)}/*** Returns an instance of the extension identified by this ExtensionId instance.* Java API* For extensions written in Scala that are to be used from Java also,* this method should be overridden to get correct return type.* {{{* override def get(system: ActorSystem): TheExtension = super.get(system)* }}}**/def get(system: ActorSystem): T = apply(system)/*** Is used by Akka to instantiate the Extension identified by this ExtensionId,* internal use only.*/def createExtension(system: ExtendedActorSystem): Toverride final def hashCode: Int = System.identityHashCode(this)override final def equals(other: Any): Boolean = this eq other.asInstanceOf[AnyRef]
}

   ExtensionId也很简单,首先这是一个trait,且有一个类型变量T,要求T是Extension的子类。其中有一个apply,通过system返回一个T的实例。createExtension没有实现。那需要继续深入registerExtension的代码。

  /*** Registers the provided extension and creates its payload, if this extension isn't already registered* This method has putIfAbsent-semantics, this method can potentially block, waiting for the initialization* of the payload, if is in the process of registration from another Thread of execution*/def registerExtension[T <: Extension](ext: ExtensionId[T]): T

   通过registerExtension的定义来看,官方注释写的也很清楚,它就是在注册一个extension,并且创建一个实例。如果这个extension已经注册过,就不再注册。

  @tailrecfinal def registerExtension[T <: Extension](ext: ExtensionId[T]): T = {findExtension(ext) match {case null ⇒ //Doesn't already exist, commence registrationval inProcessOfRegistration = new CountDownLatch(1)extensions.putIfAbsent(ext, inProcessOfRegistration) match { // Signal that registration is in processcase null ⇒ try { // Signal was successfully sentext.createExtension(this) match { // Create and initialize the extensioncase null ⇒ throw new IllegalStateException(s"Extension instance created as 'null' for extension [$ext]")case instance ⇒extensions.replace(ext, inProcessOfRegistration, instance) //Replace our in process signal with the initialized extensioninstance //Profit!}} catch {case t: Throwable ⇒extensions.replace(ext, inProcessOfRegistration, t) //In case shit hits the fan, remove the inProcess signalthrow t //Escalate to caller} finally {inProcessOfRegistration.countDown //Always notify listeners of the inProcess signal}case other ⇒ registerExtension(ext) //Someone else is in process of registering an extension for this Extension, retry}case existing ⇒ existing.asInstanceOf[T]}}

   我们来看看registerExtension的具体实现,它首先通过findExtension查找对应的ExtensionId是否已经注册,如果已经注册,则直接返回找到的结果,否则就进行创建。在case null分支中,有一个CountDownLatch。我们有必要简要介绍一下这个类的作用和使用方法。

“CountDownLatch典型用法1:某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为n new CountDownLatch(n) ,每当一个任务线程执行完毕,就将计数器减1 countdownlatch.countDown(),当计数器的值变为0时,在CountDownLatch上 await() 的线程就会被唤醒”

  也就是说registerExtension是会保证线程安全的,以保证Extension只被加载一次。extensions会通过putIfAbsent方法插入ExtensionId与inProcessOfRegistration的键值对,当然了extensions是一个ConcurrentHashMap。如果key不存在,即第一次注册的时候,则把键值对插入并返回null。所以第一次注册会命中case null,然后把当前ActorSystem传给createExtension方法创建Extension实例。如果创建成功,就会替换extensions中ExtensionId对应的value为新创建的Extension实例(替换之前是inProcessOfRegistration这个CountDownLatch),最后执行countDown,计数器变成0。如果创建失败呢?会抛出一个IllegalStateException异常或其他异常,收到异常后,会把ExtensionId对应的value变成对应的Throwable信息。那么如果putIfAbsent插入失败呢,也就是ExtensionId已经有对应的value了,会递归执行registerExtension重新注册,既然有值了为啥还要重新注册呢?因为对应的值有三种情况:Extension实例、Throwable、CountDownLatch。所以需要重新注册。

  另外CountDownLatch一定会有await,那么啥时候await呢。别急,还有findExtension没有分析呢。

 /*** Returns any extension registered to the specified Extension or returns null if not registered*/@tailrecprivate def findExtension[T <: Extension](ext: ExtensionId[T]): T = extensions.get(ext) match {case c: CountDownLatch ⇒c.await(); findExtension(ext) //Registration in process, await completion and retrycase t: Throwable ⇒ throw t //Initialization failed, throw same againcase other ⇒other.asInstanceOf[T] //could be a T or null, in which case we return the null as T}

   很显然,findExtension会对查询到的结果进行判断,如果是CountDownLatch就调用await进行等待,等待其他线程的registerExtension执行完毕,然后递归调用findExtension;如果其他线程注册完了返回异常,则此处也简单的抛出异常;如果返回其他类型的数据,则把它转化成T的一个实例,也就是我们自定义的Extension,那如果返回null呢?那就返回null喽。

  至此registerExtension分析完毕,它以线程安全的方式保证Extension被加载一次,也就是createExtension方法只被调用一次。那么如何根据ActorSystem创建我们自定义的Extension就非常灵活了。

  我们来看一下官网的例子。

class CountExtensionImpl extends Extension {//Since this Extension is a shared instance// per ActorSystem we need to be threadsafeprivate val counter = new AtomicLong(0)//This is the operation this Extension providesdef increment() = counter.incrementAndGet()
}

   上面是我们自定义的一个Extension,它非常简单,就是一个计数器,且increment()保证线程安全。

object CountExtensionextends ExtensionId[CountExtensionImpl]with ExtensionIdProvider {//The lookup method is required by ExtensionIdProvider,// so we return ourselves here, this allows us// to configure our extension to be loaded when// the ActorSystem starts upoverride def lookup = CountExtension//This method will be called by Akka// to instantiate our Extensionoverride def createExtension(system: ExtendedActorSystem) = new CountExtensionImpl/*** Java API: retrieve the Count extension for the given system.*/override def get(system: ActorSystem): CountExtensionImpl = super.get(system)
}

   上面是一个ExtensionId,还继承了ExtensionIdProvider,ExtensionIdProvider源码如下,其实就是用来查找ExtensionId的,这样就能够通过配置文件自动加载了。

/*** To be able to load an ExtensionId from the configuration,* a class that implements ExtensionIdProvider must be specified.* The lookup method should return the canonical reference to the extension.*/
trait ExtensionIdProvider {/*** Returns the canonical ExtensionId for this Extension*/def lookup(): ExtensionId[_ <: Extension]
}

   可以看出createExtension就是new了一个CountExtensionImpl,没有把ExtendedActorSystem传给CountExtensionImpl。其实在稍微复杂点的Extension里面是可以接收ExtendedActorSystem参数的,有了对ExtendedActorSystem的引用,我们就可以调用ExtendedActorSystem的所有公开的方法。如果你要问我ExtendedActorSystem都有哪些公开的方法或者说,有了ExtendedActorSystem可以做什么,我是拒绝回答的。有了ExtendedActorSystem你还不是想干啥就干啥?哈哈。

akka-extensions

CountDownLatch的简单理解

转载于:https://www.cnblogs.com/gabry/p/9403264.html

http://www.jmfq.cn/news/5296771.html

相关文章:

  • 京东做代码的网站吗/网站搜索引擎拓客
  • 愿景 做中国最受欢迎的互联网网站/国内重大新闻10条
  • 如何增加网站权重/十大免费cms建站系统介绍
  • 单位的网站的建设/seo职位要求
  • 电子商务网站建设哪本教材比较适合中等专业学校用/免费发布外链
  • 香港特别行政区的区花是什么花/天津seo代理商
  • dedecms做电商网站/全国疫情高峰感染高峰进度
  • 团队如何分工做网站/全国免费发布广告信息平台
  • 黑客软件/开封网站优化公司
  • 小公司企业简介怎么写/黑帽seo优化软件
  • 软件公司网站素材/优化设计七年级下册语文答案
  • diango是做网站的后端吗/如何制作百度网页
  • 国外做电商平台的网站还有什么/优化大师的作用
  • 做网站要固定电话/软文街
  • 哪些网站做科技专题/百度seo优化招聘
  • 用PS怎么做网站图片/站长工具网站排名
  • 做网站赚钱多吗/口碑营销的定义
  • 可以做宣传的网站有哪些/营销案例最新
  • wordpress文章网格/seo链接优化
  • 房门户网站如何做优化/厦门关键词优化报价
  • 现在有男的做外围女网站客服吗/福州百度网站排名优化
  • 网站建设交易平台/灰色词首页排名接单
  • 为什么要做一个营销型网站/百度竞价推广是什么工作
  • 建设一个网站可以做什么/线上营销平台有哪些
  • 商洛市住户和城乡建设局网站信息价/世界球队最新排名
  • 可以做用户旅程图的网站/站长网站
  • python做网站验证码/seo每日一贴
  • 西部空间怎样上传网站/百度联盟一天多少收入
  • 镇江品牌网站建设/青岛seo优化公司
  • 郴州市做网站/百度推广代理商有哪些