无浪费编码

本文介绍了如何通过减少软件堆栈中的浪费来高效解决有意义的事件处理问题。

Java通常被视为无法在低内存环境中高效运行的内存猪。 目的是证明许多人认为不可能的事情,有意义的java程序几乎可以在没有内存的情况下运行。 示例流程
在Java的单个线程上,零内存gc的3MB堆中每秒有220万个csv记录

您将了解Java应用程序中主要浪费区域所在的位置以及可以用来减少浪费的模式。 引入了零成本抽象的概念,并且可以通过代码生成在编译时自动进行许多优化。 一个Maven插件简化了开发人员的工作流程。

我们的目标不是高性能,而是作为最大化效率的副产品。 该解决方案使用Fluxtion ,与现有的Java事件处理框架相比,它占用的资源很少 。

计算与气候

当前,气候变化及其原因引起许多人的极大关注。 计算是主要的排放源,产生的碳足迹与整个航空业相同 。 在缺乏规定计算能耗的法规的情况下,作为工程师,我们必须承担生产高效系统并与创建它们的成本相平衡的责任。

在2019年伦敦Infoq会议的小组会议上, 马丁·汤普森 ( Martin Thompson)热情洋溢地谈到了建筑节能计算系统。 他指出,控制浪费是最大程度降低能耗的关键因素。 Martin的评论引起了我的共鸣,因为Fluxtion背后的核心理念是消除不必要的资源消耗。 小组会议是本文的灵感。

加工要求

处理示例的要求是:

  • 使用零gc在3MB的堆中运行
  • 仅使用标准的Java库,没有“不安全”的优化
  • 读取包含数百万行输入数据的CSV文件
  • 输入是一组未知事件,没有预先加载数据
  • 数据行是异构类型
  • 处理每一行以计算多个汇总值
  • 计算取决于行类型和数据内容
  • 将规则应用于汇总并计算违反规则的次数
  • 数据随机分布以防止分支预测
  • 根据行输入值进行分区计算
  • 收集分区计算并将其分组到汇总视图中
  • 在文件末尾发布摘要报告
  • 使用高级功能的纯Java解决方案
  • 没有准时热身

头寸和利润监控示例

CSV文件包含一系列资产的交易和价格,每行一条记录。 每个资产的头寸和利润计算都划分在其自己的存储空间中。 资产计算会在每个匹配的输入事件上更新。 所有资产的利润将汇总为投资组合利润。 每项资产都监视其当前头寸/利润状态,并在其中一项违反预设限制时记录计数。 投资组合的利润将受到监控,并计算违约损失。

针对每个传入事件在资产和投资组合级别验证规则。 随着事件流式传输到系统中,违反规则的计数也会更新。

行数据类型

href="https://github.com/gregv12/articles/blob/article_may2019/2019/may/trading-monitor/src/main/java/com/fluxtion/examples/tradingmonitor/AssetPrice.java" target="_blank" rel="noopener noreferrer">AssetPrice - [price: double] [symbol: CharSequence]

Deal       - [price: double] [symbol: CharSequence] [size: int]

样本数据

CSV文件的每种类型都有一个标题行,以允许动态列位置映射到字段。 每行前面都有要编组的目标类型的简单类名。 记录示例集,包括标题:

Deal,symbol,size,price
AssetPrice,symbol,price
AssetPrice,FORD,15.0284
AssetPrice,APPL,16.4255
Deal,AMZN,-2000,15.9354

计算说明

资产计算按符号划分,然后收集到资产组合计算中。

分区资产计算

asset position  = sum(Deal::size)
deal cash value = (Deal::price) X (Deal::size) X -1
cash position   = sum(deal cash value)
mark to market  = (asset position) X (AssetPrice::price)
profit          = (asset mark to market) + (cash position)

投资组合计算

portfolio profit = sum(asset profit)

监控规则

asset loss > 2,000
asset position outside of range +- 200
portfolio loss > 10,000

注意:

  1. 当通知程序指示违反规则时,将进行计数。 通知程序仅在第一个违规时触发,直到将其重置。 当规则再次变得有效时,将重置通知程序。
  2. 正交易::大小是买入,负值是卖出。

执行环境

为确保满足内存要求(零gc和3MB堆),
使用Epsilon无操作垃圾收集器,最大堆大小为3MB。 如果在整个过程的生命周期中分配了超过3MB的内存,则JVM将立即退出,并显示内存不足错误。

运行示例: 从git克隆,并在trading-monitor项目的根目录中,运行dist目录中的jar文件,以生成一个包含400万行的测试数据文件。

git clone --branch  article_may2019 https://github.com/gregv12/articles.git
cd articles/2019/may/trading-monitor/
jdk-12.0.1\bin\java.exe -jar dist\tradingmonitor.jar 4000000

默认情况下,tradingmonitor.jar处理data / generated-data.csv文件。 使用上面的命令,输入数据应具有400万行,并且长度为94MB,可以执行。

结果

要执行测试,请运行不带参数的tradingmonitor.jar:

jdk-12.0.1\bin\java.exe -verbose:gc -Xmx3M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -jar dist\tradingmonitor.jar

对400万行执行测试,摘要结果为:

Process row count     =    4 million
Processing time       =    1.815 seconds
Avg row exec time     =  453 nano seconds
Process rate          =    2.205 million records per second
garbage collections   =    0
allocated mem total   = 2857 KB
allocated mem per run =   90 KB
OS                    = windows 10
Processor             = Inte core i7-7700@3.6Ghz
Memory                = 16 GB
Disk                  = 512GB Samsung SSD PM961 NVMe

注意:结果来自没有JIT预热的第一次运行。 在jit预热后,代码执行时间缩短了大约10%。 分配的总内存为2.86Mb,其中包括启动JVM。

通过分析Epsilon的输出,我们估计应用程序为6次运行分配了15%的内存,即每次运行分配90KB。 应用程序数据很可能适合L1缓存,此处需要进行更多调查。

输出量

测试程序每次循环打印6次,每次打印出结果,Epsilon在运行结束时记录内存统计信息。

jdk-12.0.1\bin\java.exe" -server -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC  -Xmx3M -verbose:gc -jar dist\tradingmonitor.jar
[0.011s][info][gc] Non-resizeable heap; start/max: 3M
[0.011s][info][gc] Using TLAB allocation; max: 4096K
[0.011s][info][gc] Elastic TLABs enabled; elasticity: 1.10x
[0.011s][info][gc] Elastic TLABs decay enabled; decay time: 1000ms
[0.011s][info][gc] Using Epsilon
[0.024s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 0M (5.11%) used
[0.029s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 0M (10.43%) used
.....
.....
[0.093s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 1M (64.62%) used
[0.097s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 2M (71.07%) usedportfolio loss gt 10k count -> 792211.0
Portfolio PnL:-917.6476000005273
Deals processed:400346
Prices processed:3599654
Assett positions:
-----------------------------
[1.849s][info][gc] Heap: 3M reserved, 3M (100.00%) committed, 2M (76.22%) used
MSFT : AssetTradePos{symbol=MSFT, pnl=484.68589999993696, assetPos=97.0, mtm=1697.0247000000002, cashPos=-1212.3388000000632, positionBreaches=139, pnlBreaches=13628, dealsProcessed=57046, pricesProcessed=514418}
GOOG : AssetTradePos{symbol=GOOG, pnl=-998.6065999999155, assetPos=-1123.0, mtm=-19610.1629, cashPos=18611.556300000084, positionBreaches=3, pnlBreaches=105711, dealsProcessed=57199, pricesProcessed=514144}
APPL : AssetTradePos{symbol=APPL, pnl=-21.881300000023202, assetPos=203.0, mtm=3405.1017, cashPos=-3426.9830000000234, positionBreaches=169, pnlBreaches=26249, dealsProcessed=57248, pricesProcessed=514183}
ORCL : AssetTradePos{symbol=ORCL, pnl=-421.9756999999504, assetPos=-252.0, mtm=-4400.4996, cashPos=3978.5239000000497, positionBreaches=103, pnlBreaches=97777, dealsProcessed=57120, pricesProcessed=513517}
FORD : AssetTradePos{symbol=FORD, pnl=112.14559999996254, assetPos=-511.0, mtm=-7797.8089, cashPos=7909.9544999999625, positionBreaches=210, pnlBreaches=88851, dealsProcessed=57177, pricesProcessed=514756}
BTMN : AssetTradePos{symbol=BTMN, pnl=943.8932999996614, assetPos=-1267.0, mtm=-19568.9417, cashPos=20512.83499999966, positionBreaches=33, pnlBreaches=117661, dealsProcessed=57071, pricesProcessed=514291}
AMZN : AssetTradePos{symbol=AMZN, pnl=-557.0849999999355, assetPos=658.0, mtm=10142.214600000001, cashPos=-10699.299599999937, positionBreaches=63, pnlBreaches=114618, dealsProcessed=57485, pricesProcessed=514345}
-----------------------------
Events proecssed:4000000
millis:1814
...
...
portfolio loss gt 10k count -> 792211.0
Portfolio PnL:-917.6476000005273
Deals processed:400346
Prices processed:3599654
Assett positions:
-----------------------------
MSFT : AssetTradePos{symbol=MSFT, pnl=484.68589999993696, assetPos=97.0, mtm=1697.0247000000002, cashPos=-1212.3388000000632, positionBreaches=139, pnlBreaches=13628, dealsProcessed=57046, pricesProcessed=514418}
GOOG : AssetTradePos{symbol=GOOG, pnl=-998.6065999999155, assetPos=-1123.0, mtm=-19610.1629, cashPos=18611.556300000084, positionBreaches=3, pnlBreaches=105711, dealsProcessed=57199, pricesProcessed=514144}
APPL : AssetTradePos{symbol=APPL, pnl=-21.881300000023202, assetPos=203.0, mtm=3405.1017, cashPos=-3426.9830000000234, positionBreaches=169, pnlBreaches=26249, dealsProcessed=57248, pricesProcessed=514183}
ORCL : AssetTradePos{symbol=ORCL, pnl=-421.9756999999504, assetPos=-252.0, mtm=-4400.4996, cashPos=3978.5239000000497, positionBreaches=103, pnlBreaches=97777, dealsProcessed=57120, pricesProcessed=513517}
FORD : AssetTradePos{symbol=FORD, pnl=112.14559999996254, assetPos=-511.0, mtm=-7797.8089, cashPos=7909.9544999999625, positionBreaches=210, pnlBreaches=88851, dealsProcessed=57177, pricesProcessed=514756}
BTMN : AssetTradePos{symbol=BTMN, pnl=943.8932999996614, assetPos=-1267.0, mtm=-19568.9417, cashPos=20512.83499999966, positionBreaches=33, pnlBreaches=117661, dealsProcessed=57071, pricesProcessed=514291}
AMZN : AssetTradePos{symbol=AMZN, pnl=-557.0849999999355, assetPos=658.0, mtm=10142.214600000001, cashPos=-10699.299599999937, positionBreaches=63, pnlBreaches=114618, dealsProcessed=57485, pricesProcessed=514345}
-----------------------------
Events proecssed:4000000
millis:1513
[14.870s][info][gc] Total allocated: 2830 KB
[14.871s][info][gc] Average allocation rate: 19030 KB/sec

废物热点

下表标识了处理循环中的功能,这些功能通常会创建示例中使用的浪费和避免浪费技术。

功能 废物来源 影响 回避
读取CSV文件 为每行分配一个新的字符串 GC 将每个字节读入一个flyweight,并在无分配解码器中进行处理
行数据持有人 为每一行分配一个数据实例 GC Flyweight单个数据实例
读取列值 为每列分配一个字符串数组 GC 将字符推送到可重复使用的字符缓冲区中
将值转换为类型 字符串到类型的转换分配内存 GC 零分配转换器CharSequence代替字符串
将col值推送给持有人 基本类型的自动装箱会分配内存。 GC 原始感知功能可推送数据。 零分配
分区数据处理 数据分区并行处理。 分配给队列的任务 GC /锁 单线程处理,无分配或锁
计算方式 自动装箱,分配中间实例的不可变类型。 无状态功能需要外部状态存储和分配 GC 生成没有自动装箱的功能。 有状态功能零分配
汇总摘要计算 将分区线程的结果推送到队列中。 需要分配和同步 GC /锁 单线程处理,无分配或锁

减少废物的解决方案

使用Fluxtion生成实现事件处理的代码。 生成解决方案允许采用零成本抽象方法,其中已编译的解决方案的开销最少。 程序员描述所需的行为,并在构建时生成满足要求的优化解决方案。 对于此示例,可以在此处查看生成的代码。

maven pom包含一个配置文件,用于使用通过以下命令执行的Fluxtion maven插件重建生成的文件:

mvn -Pfluxtion install

文件读取

从输入文件中提取数据作为一系列CharEvents ,并将其发布到csv类型的marshaller。 每个字符都可以从文件中单独读取,然后推入CharEvent中。 由于重复使用了同一CharEvent实例,因此初始化后不会分配任何内存。 用于流CharEvents逻辑位于CharStreamer类。 整个96 MB的文件可以读取,应用程序在堆上分配的内存几乎为零。

CSV处理

向Javabean添加@CsvMarshaller会通知Fluxtion在生成时生成csv解析器。 Fluxtion在应用程序类中扫描@CsvMarshaller批注,并在构建过程中生成封送处理程序。 有关示例,请参见AssetPrice.java ,它会生成AssetPriceCsvDecoder0 。 解码器处理CharEvents并将行数据编组到目标实例中。

生成的CSV解析器采用上表中概述的策略,避免了不必要的内存分配,并为处理的每一行重用了对象实例:

  • 字符缓冲区的单个可重用实例存储行字符
  • 轻量级可重用实例是编组列数据的目标
  • 直接从CharSequence转换为目标类型,而无需创建中间对象。
  • 如果在目标实例中使用了CharSequence,则不会创建任何字符串,则将使用一个轻量级的Charsequence。

有关将无用字符转换为目标字段的示例,请参见AssetPriceCsvDecoder中的upateTarget()方法:

计算方式

该构建器使用Fluxtion流API描述资产计算。 声明形式类似于Java流api,但是建立了实时事件处理图。 标有注释的方法
maven插件调用@SepBuilder以生成静态事件处理器。 以下代码描述了资产的计算,请参见
FluxtionBuilder :

@SepBuilder(name = "SymbolTradeMonitor",packageName = "com.fluxtion.examples.tradingmonitor.generated.symbol",outputDir = "src/main/java",cleanOutputDir = true)public void buildAssetAnalyser(SEPConfig cfg) {//entry points subsrcibe to eventsWrapper<Deal> deals = select(Deal.class);Wrapper<AssetPrice> prices = select(AssetPrice.class);//result collector, and republish as an event sourceAssetTradePos results = cfg.addPublicNode(new AssetTradePos(), "assetTradePos");eventSource(results);//calculate derived valuesWrapper<Number> cashPosition = deals.map(multiply(), Deal::getSize, Deal::getPrice).map(multiply(), -1).map(cumSum());Wrapper<Number> pos = deals.map(cumSum(), Deal::getSize);Wrapper<Number> mtm = pos.map(multiply(), arg(prices, AssetPrice::getPrice));Wrapper<Number> pnl = add(mtm, cashPosition);//collect into resultscashPosition.push(results::setCashPos);pos.push(results::setAssetPos);mtm.push(results::setMtm);pnl.push(results::setPnl);deals.map(count()).push(results::setDealsProcessed);prices.map(count()).push(results::setPricesProcessed);//add some rules - only fires on first breachpnl.filter(lt(-200)).notifyOnChange(true).map(count()).push(results::setPnlBreaches);pos.filter(outsideBand(-200, 200)).notifyOnChange(true).map(count()).push(results::setPositionBreaches);//human readable names to nodes in generated code - not required deals.id("deals");prices.id("prices");cashPosition.id("cashPos");pos.id("assetPos");mtm.id("mtm");pnl.id("pnl");}

功能描述被转换为有效的命令形式以执行。 生成的事件处理器SymbolTradeMonitor是AssetPrice和Deal事件的入口点。 事件处理器使用生成的帮助器类来计算聚合,这些帮助器类在此处 。

处理器从分区程序接收事件,并调用帮助程序函数以提取数据并调用计算函数,将聚合结果存储在节点中。 汇总值被推送到结果实例AssetTradePos的字段中。 不创建任何中间对象,无需自动装箱即可处理任何原始计算。 计算节点从父实例引用数据,执行期间没有数据对象在图形周围移动。 图形初始化后,处理事件时便没有内存分配。

与代码同时生成代表资产计算处理图的图像,如下所示:

资产处理图

FluxtionBuilderbuilder类的buildPortfolioAnalyser方法中描述了投资组合的一组类似计算,生成了PortfolioTradeMonitor事件处理程序。 AssetTradePos从SymbolTradeMonitor发布到PortfolioTradeMonitor。 用于投资组合计算的生成文件位于此处 。

分区和收集

所有计算,分区和收集操作都在同一单个线程中进行,不需要锁。 不需要不变的对象,因为没有并发问题要处理。 封送处理的事件具有隔离的私有作用域,由于在事件处理过程中生成的事件处理器控制实例的生命周期,因此可以安全地重用实例。

系统数据流

下图显示了系统的完整数据流,从磁盘上的字节到已发布的摘要报告。 紫色框是生成的一部分,蓝色框是可重用的类。

结论

在本文中,我证明了可以解决Java中复杂的事件处理问题而几乎没有浪费。 在声明/功能方法中使用了高级功能来描述所需的行为,并且生成的事件处理器符合描述的要求。 一个简单的注释触发编组器生成。 生成的代码是JIT可以轻松优化的简单命令式代码。 不会进行不必要的内存分配,并且将尽可能多地重用实例。

采用这种方法,具有低资源消耗的高性能解决方案在普通程序员的掌握范围内。 传统上,只有具有多年经验的专业工程师才能获得这些结果。

尽管这种方法在Java中很新颖,但在其他语言中却很熟悉,通常称为零成本抽象。

在当今基于云的计算环境中,按消耗的单位收取资源费用。 任何节省能源的解决方案也将对公司的底线产生积极的好处。

翻译自: https://www.javacodegeeks.com/2019/06/waste-free-coding.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/341607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

485光纤转换器产品分类介绍

485转换器用于点对点、点对多点通讯、工业控制自动化、道路交通控制自动化、智能卡、考勤、门禁、售饭系统、工业集散分布系统、闭路监控、安防系统、POS系统、楼宇自控系统、自助银行系统。接下来就由飞畅科技的小编来为大家详细介绍下485转换器的分类&#xff0c;一起来看看吧…

RS232与串口通信的4个注意事项详解

RS232和串口通信&#xff0c;用于串口设备的数据采集软件&#xff0c;包括仪表、天平、秤或任何RS232仪器。WinWedge直接将数据捕获到Excel、Access或任何Windows应用程序或网页。它甚至可以从COM端口发送命令&#xff0c;因此您可以通过热键&#xff0c;按钮或DDE控制您的设备…

RS485集线器知识详解

集线器的英文名称就是我们通常见到的“HUB”&#xff0c;英文“HUB”是“中心”意思&#xff0c;集线器的主要功能是对接收到的信号进行再生整形放大&#xff0c;以扩大网络的传输距离&#xff0c;同时把所有节点集中在以它为中心的节点上。 集线器工作原理 它工作于OSI参考模…

HttpMate简介

没有人愿意编写不良代码。 没有人会想到“我要创建最纠结和最不可读的代码&#xff0c;并确保它不可扩展且难以修改或浏览”&#xff0c;从而开始了应用程序开发。 首先要有良好的意愿&#xff0c;甚至可能要牢记所有Clean Code和SOLID原则。 但是&#xff0c;折衷方案通常以所…

rs485转rs232串口转换器常见的故障剖析

在实际应用中&#xff0c;rs485串口、rs232串口可能会用于同一个传输线路上&#xff0c;但这两个接口的电气特性不一致&#xff0c;数据不能从这两个串口中相互传输或是rs232串口功能不足需要额外用到rs485串口&#xff0c;这两种情况都可以使用rs485转换器。 rs485转rs232串口…

TDMoverIP是什么?tdmoverip产品特性介绍

tdmoverip伪线路仿真产品&#xff0c;也称为IP电路仿真器或反向网桥。接下来就由飞畅科技的小编来为大家详细讲解下TDMoverIP及其产品特性&#xff0c;一起来看看吧&#xff01; tdmoverip简介 该系列基于TDM over IP技术&#xff0c;实现端到端电路仿真(PWE3)&#xff0c;符合…

java用i/o查看文件_Java文件I / O基础

java用i/o查看文件Java 7引入了java.nio.file包&#xff0c;以提供对文件I / O的全面支持。 除了许多其他功能之外&#xff0c;该软件包还包括Files类&#xff08;如果您已经使用此类&#xff0c;则可以在这里停止阅读&#xff09;。 文件包含许多静态方法&#xff0c;可在处理…

PCM复用设备和PDH设备的区别介绍

首先PCM设备和PDH设备是完全不同的两者设备。PCM是综合业务接入设备&#xff0c;PDH设备是光传输设备。接下来就由飞畅科技的小编来为大家详细介绍下PCM复用设备和PDH设备的区别&#xff0c;一起来看看吧&#xff01; 数字信号是对连续变化的模拟信号进行抽样、量化和编码产生…

定义资源

在Fielding的论文中 &#xff0c;资源被描述为&#xff1a; “可以命名的任何信息”……“文档或图像&#xff0c;临时服务&#xff08;例如&#xff0c;“洛杉矶今天的天气”&#xff09;&#xff0c;其他资源的集合&#xff0c;非虚拟对象&#xff08;例如&#xff0c;人&am…

E1 PCM复用设备能当程控交换机用吗?

E1 PCM复用设备能当程控交换机用吗&#xff1f;这个问题在平时与用户沟通中发现&#xff0c;发现有不少用户认为E1 PCM复用设备可以当程控交换机使用&#xff0c;不仅能实现电话线远端延伸&#xff0c;还可以实现电话机交换功能。 其实这个观点是错误的&#xff0c;E1 PCM复用…

PCM设备能在公网使用吗?

正如标题所言&#xff0c;PCM设备能否在公网使用吗&#xff1f;首先我们可以了解一下公网的概念。“公网”也可以理解为“外网”&#xff0c;就是指公共的网络&#xff0c;用户可以使用这个网络相互访问对方。 其实&#xff0c;笔者认为“PCM能在公网使用”或“PCM不能在公网使…

日月神话_常见的Java神话

日月神话这些问题在任何面试中都可能太过高级而无法提出&#xff0c;因为它们可能会使候选人推迟。 不管怎样&#xff0c;他们可能会在您自己的时间练习。 误解1&#xff09;System.exit&#xff08;0&#xff09;阻止最终被调用 为什么这样的代码 System.setSecurityManager…

PCM设备是做什么的? PCM作用是什么?

PCM可以提供用户从2M到155M速率的数字数据专线业务&#xff0c;也可以提供话音、图象传送、远程教学等其他业务。那么&#xff0c;PCM设备是做什么的? PCM作用是什么&#xff1f;接下来我们就跟随飞畅科技的小编一起来看看吧&#xff01; PCM的含义&#xff1a; 1、PCM&…

Iceberg:浅析基于Snapshot的事务过程

MVCC事务&#xff08;乐观锁&#xff09; 我们知道&#xff0c;Iceberg基于Snapshot&#xff08;快照机制&#xff09;实现了乐观无锁地数据并发读写能力&#xff08;MVCC&#xff0c;Multi Versions Concurrency Controll&#xff09;&#xff0c;默认提供了快照级别的事务隔…

关于“最终”的最终决定

在Java中&#xff0c;过度使用final感觉就像是SHOUTING。 在很多时候它已经过时且不合适。 Java和JavaScript 这主要是关于Java中的final关键字&#xff0c;但是我对JavaScript中与之对应的const看法略有变化。 我可以认为const是一件好事&#xff0c;而final是一件坏事&#…

PCM设备在电网系统中的应用介绍

近年来&#xff0c;随着我国社会经济的快速发展和电力通信行业的不断进步&#xff0c;通信网络技术和网络系统不断完善和改进的同时&#xff0c;网络系统运行过程中也出现了很多的问题&#xff0c;要对其进行优化&#xff0c;否则可能影响电力通信网络的正常运行电力通信网络系…

PCM设备在雷达通信系统应用

PCM设备系统是目前国内企业最常用的综合接入通信设备&#xff0c;PCM设备所具优势众多&#xff0c;因此它能成为目前企业最常用的通信传输接入设备之一&#xff0c;而且在类似雷达通信系统等重要行业中广泛应用着。 PCM设备利用标准的E1数据传输通道&#xff0c;采用PCM制式&a…

ejb的maven_针对新手的Java EE7和Maven项目-第3部分-定义ejb服务和jpa实体模块

ejb的maven从前面的部分恢复 第1部分 第2部分 我们在第三部分继续介绍&#xff0c;我们已经有一个父pom&#xff0c;并且已经为我们的war模块定义了pom。 在我们的原始设置中&#xff0c;我们定义了我们的应用程序将包含一个ejb jar形式的服务jar。 这是我们的Enterprise Jav…

PCM设备终端烧毁板卡是什么原因?

最近&#xff0c;有新客服反映他们之前在某家设备厂家买了PCM设备&#xff0c;老是会烧毁终端板。所以另外选择了我们飞畅科技。那么&#xff0c;PCM设备终端烧毁板卡是什么原因呢&#xff1f;接下来飞畅科技的小编就来为大家具体分析下PCM设备终端烧毁板卡的原因&#xff0c;一…

全部隐藏!

在较早的文章中 &#xff0c;我写了以下几句话&#xff1a; 在面向对象的代码库中&#xff0c;该工具包应尽可能离散。 使用开发套件的次数越多&#xff0c;您的代码实际面向对象的次数就越少&#xff0c;或者您的抽象并不是最好的。 。 我认为有必要详细说明这一点&#xff0…