IaaS: Infrastructure-as-a-Service(基础设施即服务) 第一层叫做IaaS,有时候也叫做Hardware-as-a-Service,以前如果你想在办公室或者公司的网站上运行一些企业应用,你需要去买服务器,或者别的高昂的硬件来控制本地应用,让你的业务运行起来。
但是现在有IaaS,你可以将硬件外包到别的地方去。IaaS公司会提供场外服务器,存储和网络硬件,你可以租用。节省了维护成本和办公场地,公司可以在任何时候利用这些硬件来运行其应用。
一些大的IaaS公司包括Amazon, Microsoft, VMWare, Rackspace和Red Hat.不过这些公司又都有自己的专长,比如Amazon和微软给你提供的不只是IaaS,他们还会将其计算能力出租给你来host你的网站。
PaaS: Platform-as-a-Service(平台即服务) 第二层就是所谓的PaaS,某些时候也叫做中间件。你公司所有的开发都可以在这一层进行,节省了时间和资源。
PaaS公司在网上提供各种开发和分发应用的解决方案,比如虚拟服务器和操作系统。这节省了你在硬件上的费用,也让分散的工作室之间的合作变得更加容易。网页应用管理,应用设计,应用虚拟主机,存储,安全以及应用开发协作工具等。
一些大的PaaS提供者有Google App Engine,Microsoft Azure,Force.com,Heroku,Engine Yard。最近兴起的公司有AppFog, Mendix 和 Standing Cloud
SaaS: Software-as-a-Service(软件即服务) 第三层也就是所谓SaaS。这一层是和你的生活每天接触的一层,大多是通过网页浏览器来接入。任何一个远程服务器上的应用都可以通过网络来运行,就是SaaS了。
你消费的服务完全是从网页如Netflix, MOG, Google Apps, Box.net, Dropbox或者苹果的iCloud那里进入这些分类。尽管这些网页服务是用作商务和娱乐或者两者都有,但这也算是云技术的一部分
一些用作商务的SaaS应用包括Citrix的GoToMeeting,Cisco的WebEx,Salesforce的CRM,ADP,Workday和SuccessFactors。
Amazon Web Services: IaaS Google Cloud 开发了一个东西叫Datastore
open cloud manifesto
关系数据库管理系统(Relational Database Management System:RDBMS)是指包括相互联系的逻辑组织和存取这些数据的一套程序 (数据库管理系统软件)。关系数据库管理系统就是管理关系数据库,并将数据逻辑组织的系统。 常用的关系数据库管理系统产品是Oracle、IBM的DB2和微软的SQL Server。 Key-Value DBs Amazon Simple DB: not an RDBMs GAE scale-out,not scale-up Scale-up,即纵向扩展架构。纵向扩展是利用现有的存储系统,通过不断增加存储容量来满足数据增长的需求 Scale-out横向扩展架构的升级通常是以节点为单位,容量和性能会同步增长。有几种方法可以实现scale-out,即横向扩展,包括集群存储系统和网格存储。但无论是哪种类型的系统,能够以一个单一系统的形式被访问和使用是scale-out解决方案的基本前提。 Datastore 不是唯一一个GAE services Document DBs Document DBs:example documents JSON/XML Column-Family DBs & Columnar DBs Graph DBs Neo4J: seems to be en route to being the de facto standard, the one that almost everyone uses: open-source Java/Scala,Cypher query language Choosing a NoSQL DB
https://www.cnblogs.com/yeungchie/
Callback 函数 proc Callback { handle } { variable line if { [catch {gets $handle line}] || [chan eof $handle]} { # 这里 gets 当获取失败,或者遇到 End Of File 时,关闭管道 catch {close $handle} } else { puts $line flush stdout } } 先创建一个函数用来接受返回值
启动外部程序 set fh [open | python SyncViewConfigure.py r] 这里运行外部程序,并返回 $fh
设置 $fh 为非阻塞模式 chan configure $fh -blocking 0 注册事件触发 Callback 函数 chan event $fh readable [list Callback $fh] 函数输入值为 $fh
前提工作: 首先检查一下centOS(虚拟机)是多少位数的,要安装对应位数的jdk;
86结尾,32位
1、下载jdk:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 进入jdk的官网,下载Linux系统对应位数的jdk。
2、进入usr文件夹中,创建java文件夹;
3、使用SSH上传jdk文件到java文件夹中;
4、查看是否上传成功;
5、使用解压命令进行解压jdk;
6、解压完成进行重命名,也可以不重命名,但是为了方便后面配置环境变量;
7、配置环境变量;
vi /etc/profile
输入o,在最后加入以下内容:
JAVA_HOME=/usr/java/jdk
JRE_HOME=/usr/java/jdk/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH
输入之后,按esc键,shift+:键,输入wq(保存退出),回车
输入source /etc/profile 使用环境变量立即生效:
验证jdk有没有安装成功:java -version
出现以下信息表示安装成功:
OO 第二单元总结
1作业综述
本单元作业共计三次,核心内容为迭代开发java程序模拟电梯的运行,要求按固定格式输出电梯运行过程中电梯到达楼层和开关门的信息以及乘客进出电梯的信息。其中,第一次仅仅有5个纵向电梯,第二次在第一次的基础上增加了横向电梯,并且允许动态增加电梯数量,但是乘客只会请求乘坐纵向电梯和横向电梯中的一种,第三次作业在第二次作业的基础上,不仅允许设置新增电梯的速度,容量,而且允许顾客提出换乘请求。可见,开发难度逐渐提高,有着不小的挑战。
2架构设计与分析。
2.1基本思路
很显然,这次作业必须以多线程的方式予以解决。我的思路来源主要是OO实验课的出校申请题目,作业架构从中借鉴了许多。总体来说,我的三次作业都是三个线程,分别为输入线程InputThread,调度器线程scheduler,电梯线程elevator。输入线程InputThread通过处理输入数据,获得乘客和新增电梯的请求request,并且将乘客请求加入waitqueue,用于调度器线程scheduler进行调度,调度器线程scheduler调度的结果便是乘客的各个请求分配到合适的电梯的外部等待队列outqueue中,也就相当于分配给了对应的电梯线程Elevator。最后再由电梯线程逐个处理从属外部队列ouequeue中的乘客请求。
2.2 UML图
StaeUML只给会员提供导出功能,因此不是会员的我只能采用分开截图的方式展示自己的UML图。
第一次作业的UML图如下:
第二次作业的UML图如下:
第三次作业的UML图如下:
2.3时序图
第一次作业时序图如下:
第二次作业的时序图如下:
第三次作业的时序图如下:
2.4迭代分析
由UML图可知,第一次作业与第二次作业架构基本一致,使用的类完全相同。相比第一次作业,第二次作业的主要区别在于:
在等待队列的类RequestQueue中增加了所在楼层floor和种类信息type的属性;
在输入线程InputThread中增加了新增电梯线程的建立过程;
在调度器线程scheduler中更改乘客请求调度方式,由原来的简单根据电梯所在楼座分配更改为在符合乘客请求的电梯种类从属的所有外部队列outqueue中寻找一个人数最少的予以分配;
在输出信息时,要根据电梯的种类选择乘客请求prequest和电梯elevator的不同属性进行输出。
由UML图可知,第三次作业相比第二次改动较大。
相比第二次作业,第三次作业区别主要在于:
新建一个名为TempRequest的类;
在乘客请求类Prequest新增在容器ArrayLis中的TempRequest属性,用于保存为调度器线程scheduler为乘客规划出的分段路线;
在调度器线程scheduler中新增多个方法,以实现对乘客请求的路线规划;
对输入线程InputThread使用了单例模式;
在输入线程InputThread中新增了numPersonRequest属性
以统计总的乘客请求数量,新增的信号量semaphore属性以判定乘客请求是否全部执行完毕,后者也是第三次作业的最大亮点,是解决轮询bug的关键。
2.5线程协作关系
输入线程InputThread通过处理输入数据,获得乘客和新增电梯的请求request,并且将乘客请求加入waitqueue,用于调度器线程scheduler进行调度,调度器线程scheduler调度的结果便是乘客的各个请求分配到合适的电梯的外部等待队列outqueue中,也就相当于分配给了对应的电梯线程Elevator。
对于前两次作业,当输入终止的时候,输入线程InputThread终止,并且修改调度器线程scheduler的属性isEnd为true,在此前提下,当调度器线程scheduler的等待队列属性waitqueue为空时,调度器线程scheduler终止,并且将所有电梯的外部队列outqueue的属性isEnd设置为true。当电梯线程elevator的从属外部队列outqueue和内部队列inqueue都为空,并且其从属外部队列的属性isEnd为true时,电梯线程终止。
第三次作业的不同之处在于,当输入结束时,输入线程InputThread还需借助其信号量属性semaphore确定所有乘客请求执行完毕才会修改调度器线程scheduler的属性isEnd为true并且终止。
3同步块的设置和锁的选择
三次作业中,我都对RequestQueue的所有方法设置为synchronized的方法,并且都在输入线程InputThread和调度器线程scheduler有部分同步语句块。在第三次作业中使用了信号量的对象semaphore,其方法acquire和release都是同步方法,此外为了修复bug在电梯线程elevator中新增了一个同步语句块。
三次作业的同步语句块都以outqueues作为锁(outqueues是外部等待队列outqueue的ArrayList),因为outqueues是输入线程InputThread和调度器线程scheduler的共享对象且输入线程InputThread对outqueues有写操作(新增电梯线程elevator时)。由于在有人进入电梯后要从该电梯的外部队列outqueue中删除该请求,是一种写操作,因此也需要用outqueue上锁。
4调度器设计
三次作业,我都选择将调度器设置为线程scheduler。
第一次作业,输入线程InputThread将输入中的乘客请求写入待分配队列waitqueue。电梯数量固定为5个,调度器线程scheduler只需依次分析waitqueue中的乘客请求对应的电梯楼座便可将乘客请求分配至相应的外部队列outqueue。由于每一个outqueue都属于一个电梯线程elevator,以上过程也就实现了对乘客请求的调度分配。
第二次作业,电梯是可以临时添置的,电梯类型也新增了横向电梯。在第一次的基础上,调度器线程scheduler需要分析waitqueue中的乘客请求是对应横向电梯还是纵向电梯,如果是纵向电梯,则在所有楼座匹配的外部队列outqueue中寻找一个人数最少的将乘客请求插入其队尾,如果是横向电梯,则在所有楼层匹配的外部队列outqueue中寻找一个人数最少的将乘客请求插入其队尾。
第三次作业,电梯不仅可以临时添置,而且添置的电梯如果是横向电梯,需要设定该电梯能在哪些楼座开关门,更麻烦的是,waitqueue中的乘客请求不再局限于同楼座或者同楼层(也就是乘客请求可能涉及换乘)。因此,调度器线程scheduler成为第三次作业最关键也是最困难的一部分设计。在这里,调度器线程scheduler需要完成规划路线和分配两个功能。waitqueue中的乘客请求也不再仅仅来源于输入线程InputThread,还可能电梯线程elevator,当一个乘客请求的规划路线没有执行全部执行完毕时,该乘客请求从电梯从属的内部队列inqueue中移除时,需要写回waiqueue。那么,面对waitqueue中的乘客请求,调度器线程scheduler首先需要判断该乘客请求是否已经规划了路线,如果已经规划,则直接分配,否则规划路线以后再分配(对应地,在乘客请求的类Prequest中新增了布尔属性planed表示乘客请求是否已经规划)。具体的分配规则是:如果waitqueue中的乘客请求对应的电梯是纵向电梯,则分配方式与第二次作业相同,如果waitqueue中的乘客请求对应的电梯是横向电梯,则应该在能执行该乘客请求规划出的路段中的横向路段请求的横向电梯中(该电梯对应的需同时满足楼层匹配和出发楼座、目的楼座都可以开关门)选择一个从属外部队列outqueue人数最少的将乘客请求分配。
5 Bug分析与修复
本单元作业完成度较高,三次公测只在第三次有一个强测点出现了tle,三次互测只在第二次被hack中了一个点(也是tle)。这两个bug都是因为当乘客请求执行完毕(前两次作业)或者临时执行完毕(第三次作业)时,从电梯从属的外部队列outqueue中移除乘客请求时没有上锁,目前已经修复。
6 关于互测
首先,本人是反对使用codeforce的互测机制,本着人道主义的原则,本人在第二单元从未尝试hack别人,但本着学习和锻炼debug能力的原则,本人还是在本地阅读他人代码并且做相关测试。
测试最有效的自然是事先准备好的自动评测程序,其中随机数据的生成方式主要是在较短时间内的投喂大量的相似乘客请求或者根据稍带策略交叉投喂方向不同的乘客请求。
较之第一单元发现的bug,本单元的bug因为多线程常无法复现。个人认为,在发现bug之后,更改根据bug类型人为构造数据或者在代码相关部分寻找逻辑漏洞或者线程不安全的隐患,这样可以一定程度提高bug复现的概率并且最终解决。
7 心得体会
线程安全的把控实属不易,全部语句同步化程序开销大,选择性同步化又容易遗漏应该同步化的语句造成线程安全问题。只有充分理解共享对象在不同线程中的穿插,才能精准把握语句块上锁的位置,这是需要大量练习和思考来体会的,第二单元的作业仅仅是让我们打开了多线程认知的大门。
我在第二单元的三次作业的层次化设计上相对第一单元进步明显,面向对象的思维初步建立。三次作业没有出现重构问题,迭代开发比较顺利,是一段很好的学习经历,希望将来再接再厉,能够真正学号OO这门课。
232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开头的元素 boolean empty() 如果队列为空,返回 true ;否则,返回 false 说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。 示例 1:
输入: [MyQueue, push, push, peek, pop, empty] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false] 解释: MyQueue myQueue = new MyQueue(); myQueue.
# 前后两个指针往中间靠class Solution: def twoSum(self, numbers: List[int], target: int) -> List[int]: i = 0 j = len(numbers) - 1 result = [] while i < j: if numbers[i] + numbers[j] > target: j -= 1 elif numbers[i] + numbers[j] < target: i += 1 else: result.append(i+1) result.append(j+1) break return result
js中关于原型和原型链有 __proto__ 、prototype、constructor 频频出现在面试题中,但是记得多了反而容易记混。
这里简单总结下每个属性的使用场景,方便记忆。
对象和函数都有 __proto__,对象的 __proto__指向构造函数的prototype,构造函数的__proto__指向 Function.prototype 对象和函数都有constructor,对象的 constructor指向构造函数,构造函数的constructor指向 Function 函数才有 prototype 函数的prototype又是一个对象,但是 Funtion.prototype 不是对象!!! 特殊记忆:typeof Function.prototype===function Object因为O大写,可以看出本质也是一个构造函数 __proto__ 指向一个原型对象,构造函数.prototype.__proto__ === Object.prototype 特殊记忆:Object.prototype.__proto__===null,因为 Object.prototype 为js 原型链的顶端。 关于js与函数的关系,这里发现一篇文章写的很好,推荐。
2.1.3 BFS中的双向广搜和A-star:https://www.acwing.com/video/455/
ps:为了督促自己学习新算法,开启每日acwing,如果顺利的话,暑假前可以把提高课刷完,然后暑假继续学习进阶课,学习过程中可以顺便看oiwiki,其他的算法学习方式感觉就没必要了,先把acwing搞定再说。
记录方式和cf一样,先把两小时的视频看完,边看边刷题,最后博客总结一下
cf的vp的话,每天就一场ok了,主要是能把vp的补题补完
acw的话,状态好的时候就多学几节吧,尽快把知识框架补齐
说来可笑,打acm打到大二了,很多稍微进阶一点的算法都不会,过去一年可以说基本只是在练习cf思维题,还是1600以下的
每天起来先花4h,把cf的vp和acw的课刷完,后面还想学的话,cf补题或者继续acw的课
ida+gdbserver 动态调试 前言 不知道是因为太简单了还是怎么的网上的文章都很少,所以在此记录一下
ida 选择remote GDB debug
Hostname 是使用gdb调试的环境ip地址
Port 是使用gdb调试的环境的开放的端口,这个需要和gdb监听的端口一致(因为这种调试本质是一种attach)
gdb 语法格式是gdbserver localhost:port <program>
参考ida官网
调试 如果一切正常的话,在ida中下完断点,启动后应该是如下的界面
gdb
ida
ps 1.在调试结束后,gdbserver无法退出,需要使用kill才可以退出
2.有时候如果在ida中调试过快(f8按的太快了)ida会卡死
3.这种调试其实很难受,因为一旦出现ida和gdb不同步的地方,就会出现一方卡死的现象,不如直接remote dbg好用
Containerization of State within Child React Components The changing of state is the reason why components re-render. If you lift all of your state up into the parent container and pass it down to child components, any update to that state in the parent affects all other sibling components. Causing many useless re-renders. By simply moving the state into that child component, saves having to use React.Memo on all sibling components.