Akka(21): Stream:实时操控:人为中断-KillSwitch
akka-stream是多线程non-blocking模式的,一般来说,运算任务提交到另外线程后这个线程就会在当前程序控制之外自由运行了。任何时候如果需要终止运行中的数据流就必须采用一种任务柄(handler)方式来控制在其它线程内运行的任务。这个handler可以在提交运算任务时获取。akka-stream提供了KillSwitch trait来支持这项功能:
/**
* A [[KillSwitch]] allows completion of [[Graph]]s from the outside by completing [[Graph]]s of [[FlowShape]] linked
* to the switch. Depending on whether the [[KillSwitch]] is a [[UniqueKillSwitch]] or a [[SharedKillSwitch]] one or
* multiple streams might be linked with the switch. For details see the documentation of the concrete subclasses of
* this interface.
*/
//#kill-switch
trait KillSwitch {
/**
* After calling [[KillSwitch#shutdown()]] the linked [[Graph]]s of [[FlowShape]] are completed normally.
*/
def shutdown(): Unit
/**
* After calling [[KillSwitch#abort()]] the linked [[Graph]]s of [[FlowShape]] are failed.
*/
def abort(ex: Throwable): Unit
}
//#kill-switch
可以想象:我们必须把这个KillSwitch放在一个流图中间,所以它是一种FlowShape的,这可以从KillSwitch的构建器代码里可以看得到:
object KillSwitches {
/**
* Creates a new [[SharedKillSwitch]] with the given name that can be used to control the completion of multiple
* streams from the outside simultaneously.
*
* @see SharedKillSwitch
*/
def shared(name: String): SharedKillSwitch = new SharedKillSwitch(name)
/**
* Creates a new [[Graph]] of [[FlowShape]] that materializes to an external switch that allows external completion
* of that unique materialization. Different materializations result in different, independent switches.
*
* For a Bidi version see [[KillSwitch#singleBidi]]
*/
def single[T]: Graph[FlowShape[T, T], UniqueKillSwitch] =
UniqueKillSwitchStage.asInstanceOf[Graph[FlowShape[T, T], UniqueKillSwitch]]
/**
* Creates a new [[Graph]] of [[FlowShape]] that materializes to an external switch that allows external completion
* of that unique materialization. Different materializations result in different, independent switches.
*
* For a Flow version see [[KillSwitch#single]]
*/
def singleBidi[T1, T2]: Graph[BidiShape[T1, T1, T2, T2], UniqueKillSwitch] =
UniqueBidiKillSwitchStage.asInstanceOf[Graph[BidiShape[T1, T1, T2, T2], UniqueKillSwitch]]
...}
akka-stream提供了single,shared,singleBidi三种KillSwitch的构建方式,它们的形状都是FlowShape。KillSwitches.single返回结果类型是Graph[FlowShape[T,T],UniqueKillSwitch]。因为我们需要获取这个KillSwitch的控制柄,所以要用viaMat来可运算化(materialize)这个Graph,然后后选择右边的类型UniqueKillSwitch。这个类型可以控制一个可运算化FlowShape的Graph,如下:
val source = Source(Stream.from(,)).delay(.second,DelayOverflowStrategy.backpressure)
val sink = Sink.foreach(println)
val killSwitch = source.viaMat(KillSwitches.single)(Keep.right).to(sink).run() scala.io.StdIn.readLine()
killSwitch.shutdown()
println("terminated!")
actorSys.terminate()
当然,也可以用异常方式中断运行:
killSwitch.abort(new RuntimeException("boom!"))
source是一个不停顿每秒发出一个数字的数据源。如上所述:必须把KillSwitch放在source和sink中间形成数据流完整链状。运算这个数据流时返回了handle killSwitch,我们可以使用这个killSwitch来shutdown或abort数据流运算。
KillSwitches.shared构建了一个SharedKillSwitch类型。这个类型可以被用来控制多个FlowShape Graph的终止运算。SharedKillSwitch类型里的flow方法可以返回终止运算的控制柄handler:
/**
* Returns a typed Flow of a requested type that will be linked to this [[SharedKillSwitch]] instance. By invoking
* [[SharedKillSwitch#shutdown()]] or [[SharedKillSwitch#abort()]] all running instances of all provided [[Graph]]s by this
* switch will be stopped normally or failed.
*
* @tparam T Type of the elements the Flow will forward
* @return A reusable [[Graph]] that is linked with the switch. The materialized value provided is this switch itself.
*/
def flow[T]: Graph[FlowShape[T, T], SharedKillSwitch] = _flow.asInstanceOf[Graph[FlowShape[T, T], SharedKillSwitch]]
用flow构建的SharedKillSwitch实例就像immutable对象,我们可以在多个数据流中插入SharedKillSwitch,然后用这一个共享的handler去终止使用了这个SharedKillSwitch的数据流运算。下面是SharedKillSwitch的使用示范:
val sharedKillSwitch = KillSwitches.shared("multi-ks")
val source2 = Source(Stream.from()).delay(.second,DelayOverflowStrategy.backpressure)
source2.via(sharedKillSwitch.flow).to(sink).run()
source.via(sharedKillSwitch.flow).to(sink).run()
scala.io.StdIn.readLine()
killSwitch.shutdown()
sharedKillSwitch.shutdown()
注意:我们先构建了一个SharedKillSwitch实例,然后在source2,source数据通道中间加入了这个实例。因为我们已经获取了sharedKillSwitch控制柄,所以不必理会返回结果,直接用via和to来连接上下游节点(默认为Keep.left)。
还有一个KillSwitches.singleBidi类型,这种KillSwitch是用来终止双流向数据流运算的。我们将在下篇讨论里介绍。
下面是本次示范的源代码:
import akka.stream.scaladsl._
import akka.stream._
import akka.actor._
import scala.concurrent.duration._
object KillSwitchDemo extends App {
implicit val actorSys = ActorSystem("sys")
implicit val ec = actorSys.dispatcher
implicit val mat = ActorMaterializer(
ActorMaterializerSettings(actorSys)
.withInputBuffer(,)
) val source = Source(Stream.from(,)).delay(.second,DelayOverflowStrategy.backpressure)
val sink = Sink.foreach(println)
val killSwitch = source.viaMat(KillSwitches.single)(Keep.right).to(sink).run() val sharedKillSwitch = KillSwitches.shared("multi-ks")
val source2 = Source(Stream.from()).delay(.second,DelayOverflowStrategy.backpressure) source2.via(sharedKillSwitch.flow).to(sink).run()
source.via(sharedKillSwitch.flow).to(sink).run() scala.io.StdIn.readLine()
killSwitch.shutdown()
sharedKillSwitch.shutdown()
println("terminated!")
actorSys.terminate() }
Akka(21): Stream:实时操控:人为中断-KillSwitch的更多相关文章
- 【STM32H7教程】第21章 STM32H7的NVIC中断分组和配置(重要)
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第21章 STM32H7的NVIC中断分组和配置( ...
- Akka(22): Stream:实时操控:动态管道连接-MergeHub,BroadcastHub and PartitionHub
在现实中我们会经常遇到这样的场景:有一个固定的数据源Source,我们希望按照程序运行状态来接驳任意数量的下游接收方subscriber.又或者我需要在程序运行时(runtime)把多个数据流向某个固 ...
- 记一个实时Linux的中断线程化问题
背景 有一个项目对实时性要求比较高,于是在linux内核上打了RT_PREEMPT补丁. 最终碰到的一个问题是,芯片本身性能不强,CPU资源不足,急需优化. 初步分析 看了下cpu占用率,除了主应用之 ...
- 【RL-TCPnet网络教程】第21章 RL-TCPnet之高效的事件触发框架
第21章 RL-TCPnet之高效的事件触发框架 本章节为大家讲解高效的事件触发框架实现方法,BSD Socket编程和后面章节要讲解到的FTP.TFTP和HTTP等都非常适合使用这种方式 ...
- [IC]浅谈嵌入式MCU软件开发之中断优先级与中断嵌套
转自:https://mp.weixin.qq.com/s?__biz=MzI0MDk0ODcxMw==&mid=2247483680&idx=1&sn=c5fd069ab3f ...
- 文件转移 互联网组成 路由器 分组交换 交换机 冲突域 网卡 数据帧的发送与接收会带来CPU开销 CPU中断 双网卡切换
https://zh.wikipedia.org/zh-cn/网段 在以太网环境中,一个网段其实也就是一个冲突域(碰撞域).同一网段中的设备共享(包括通过集线器等设备中转连接)同一物理总线,在这一总线 ...
- ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务
★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...
- s5pv210中断体系
一.什么是中断? 1.中断的发明是用来解决宏观上的并行需要的.宏观就是从整体上来看,并行就是多件事情都完成了. 2.微观上的并行,就是指的真正的并行,就是精确到每一秒甚至每一刻,多个事情都是在同时进行 ...
- CUDA ---- Stream and Event
Stream 一般来说,cuda c并行性表现在下面两个层面上: Kernel level Grid level 到目前为止,我们讨论的一直是kernel level的,也就是一个kernel或者一个 ...
随机推荐
- STL—vector
前面介绍了STL对象的构造与析构以及内存的配置与释放,那具体的容器是怎么应用STL的空间配置器的呢?这篇先介绍STL的容器vector. vector的数据成员 vector只有4个数据成员:3个迭代 ...
- C#常用8种排序算法实现以及原理简介
public static class SortExtention { #region 冒泡排序 /* * 已知一组无序数据a[1].a[2].--a[n],需将其按升序排列.首先比较a[1]与a[2 ...
- 【转载】CANoe 入门 Step by step系列(二)CAPL编程
来源:http://www.cnblogs.com/dongdonghuihui/archive/2012/09/26/2704619.html CAPL就是Communication Applica ...
- hashcode-equals方法
package com.charles.collection; import java.util.HashSet; import java.util.Set; public class Point { ...
- 机器学习 —— 基础整理(六)线性判别函数:感知器、松弛算法、Ho-Kashyap算法
这篇总结继续复习分类问题.本文简单整理了以下内容: (一)线性判别函数与广义线性判别函数 (二)感知器 (三)松弛算法 (四)Ho-Kashyap算法 闲话:本篇是本系列[机器学习基础整理]在time ...
- Redux源码分析之compose
Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...
- POJ3660 Cow Contest floyd传递闭包
Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming con ...
- python 密码学编程 -- 2
接上一篇随笔 ******************************************************************** * quote : "http://i ...
- java垃圾回收过程
对于年轻代,刚开始创建的对象都是放置在eden区的,而将年轻代分成3个部分,主要是为了生命周期短的对象尽量留在年轻代.当eden区申请不到空间的时候,进行minorGC,把存活的对象拷贝到survio ...
- JVM学习笔记五:虚拟机类加载机制
类加载生命周期 类加载生命周期:加载.验证.准备.解析.初始化.使用.卸载 类加载或初始化过程什么时候开始? 遇到new.getstatic.putstatic或invokestatic这4条字节码指 ...