Tiny并行计算框架之复杂演示样例
问题来源 很感谢@doctorwho的问题:
假如职业介绍所来了一批生产汽车的工作,如果生产一辆汽车任务是这种:搭好底盘、拧4个轮胎、安装发动机、安装4个座椅、再装4个车门、最后安装顶棚。
之间有的任务是能够并行计算的(比方拧4个轮胎,安装发动机和安装座椅),有的任务有前置任务(比方先装好座椅。才干装车门和顶棚)。让两组包工头组织两种类型的工作:将工人分成两种类型,就可以并行计算的放在同一组内,由职业介绍所来控制A组包工头做完的任务交给B组包工头。中间环节的半成品保存到Warehouse中。是这样使用TINY框架来生产汽车么?
接下来。我就用Tiny并行计算框架来展示一下这个演示样例,在编写演示样例的时候,发现了一个BUG。这也充分体现了开源的精神与价值。再次感谢@doctorwho。
问题分析
doctorwho的问题还是比較复杂的。可是实际上道理是一样的。因此我把问题简化成以下的过程
第一步:构建底盘
第二步:并行进行安装引擎。座位和轮胎
第三步:并行进行安装门及车顶
因为我和doctorwho都不是造车行家,因此就不用纠结这么造是不是合理了,如果这么做就是合理的。
代码实现
按我前面说的过程。工人是必需要有的,因此我们首先构建工人:
第一步的底盘构建工人
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class StepFirstWorker extends AbstractWorker { public StepFirstWorker() throws RemoteException { super("first"); } @Override protected Warehouse doWork(Work work) throws RemoteException { System.out.println(String.format("%s 构建底盘完毕.", work.getInputWarehouse().get("carType"))); Warehouse outputWarehouse = work.getInputWarehouse(); outputWarehouse.put("baseInfo", "something about baseInfo"); return outputWarehouse; } } |
因为第二步工人有好几个类型。因此再搞个第二步抽象工人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public abstract class StepThirdWorker extends AbstractWorker { public StepThirdWorker() throws RemoteException { super("third"); } protected boolean acceptMyWork(Work work) { String workClass = work.getInputWarehouse().get("class"); if (workClass != null) { return true; } return false; } protected Warehouse doMyWork(Work work) throws RemoteException { System.out.println(String.format("Base:%s ", work.getInputWarehouse().get("baseInfo"))); System.out.println(String.format("%s is Ok", work.getInputWarehouse().get("class"))); return work.getInputWarehouse(); } } |
接下来构建第二步的引擎工人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class StepSecondEngineWorker extends StepSecondWorker { public static final String ENGINE = "engine"; public StepSecondEngineWorker() throws RemoteException { super(); } public boolean acceptWork(Work work) { return acceptMyWork(work); } protected Warehouse doWork(Work work) throws RemoteException { return super.doMyWork(work); } } |
第二步的座位工人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class StepSecondSeatWorker extends StepSecondWorker { public static final String SEAT = "seat"; public StepSecondSeatWorker() throws RemoteException { super(); } public boolean acceptWork(Work work) { return acceptMyWork(work); } protected Warehouse doWork(Work work) throws RemoteException { return super.doMyWork(work); } } <div> </div> |
第二步的轮胎工人:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class StepSecondTyreWorker extends StepSecondWorker { public static final String TYRE = "tyre"; public StepSecondTyreWorker() throws RemoteException { super(); } public boolean acceptWork(Work work) { return acceptMyWork(work); } protected Warehouse doWork(Work work) throws RemoteException { return super.doMyWork(work); } } |
同理,第三步也是大同小异的。
第三步的抽象工人类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public abstract class StepThirdWorker extends AbstractWorker { public StepThirdWorker() throws RemoteException { super("third"); } protected boolean acceptMyWork(Work work) { String workClass = work.getInputWarehouse().get("class"); if (workClass != null) { return true; } return false; } protected Warehouse doMyWork(Work work) throws RemoteException { System.out.println(String.format("Base:%s ", work.getInputWarehouse().get("baseInfo"))); System.out.println(String.format("%s is Ok", work.getInputWarehouse().get("class"))); return work.getInputWarehouse(); } } |
第三步的车门工人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class StepThirdDoorWorker extends StepThirdWorker { public static final String DOOR = "door"; public StepThirdDoorWorker() throws RemoteException { super(); } public boolean acceptWork(Work work) { return acceptMyWork(work); } @Override protected Warehouse doWork(Work work) throws RemoteException { return super.doMyWork(work); } } |
第三步的车顶工人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class StepThirdRoofWorker extends StepThirdWorker { public static final String ROOF = "roof"; public StepThirdRoofWorker() throws RemoteException { super(); } public boolean acceptWork(Work work) { return acceptMyWork(work); } protected Warehouse doWork(Work work) throws RemoteException { return super.doMyWork(work); } } |
以上就把工人都构建好了,我们前面也说过。假设要进行任务分解,是必需要构建任务分解合并器的,这里简单起见。仅仅实现任务分解了。
第二部的任务分解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class SecondWorkSplitter implements WorkSplitter { public List<Warehouse> split(Work work, List<Worker> workers) throws RemoteException { List<Warehouse> list = new ArrayList<Warehouse>(); list.add(getWareHouse(work.getInputWarehouse(), "engine")); list.add(getWareHouse(work.getInputWarehouse(), "seat")); list.add(getWareHouse(work.getInputWarehouse(), "seat")); list.add(getWareHouse(work.getInputWarehouse(), "seat")); list.add(getWareHouse(work.getInputWarehouse(), "seat")); list.add(getWareHouse(work.getInputWarehouse(), "tyre")); list.add(getWareHouse(work.getInputWarehouse(), "tyre")); list.add(getWareHouse(work.getInputWarehouse(), "tyre")); list.add(getWareHouse(work.getInputWarehouse(), "tyre")); return list; } private Warehouse getWareHouse(Warehouse inputWarehouse, String stepClass) { Warehouse warehouse = new WarehouseDefault(); warehouse.put("class", stepClass); warehouse.putSubWarehouse(inputWarehouse); return warehouse; } } |
从上面能够看到,构建了一个引擎的仓库。4个座位仓库,4个轮胎仓库。呵呵,既然能并行。为啥不让他做得更快些?
接下来是第三步的任务分解器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class ThirdWorkSplitter implements WorkSplitter { public List<Warehouse> split(Work work, List<Worker> workers) throws RemoteException { List<Warehouse> list = new ArrayList<Warehouse>(); list.add(getWareHouse(work.getInputWarehouse(), "door")); list.add(getWareHouse(work.getInputWarehouse(), "door")); list.add(getWareHouse(work.getInputWarehouse(), "door")); list.add(getWareHouse(work.getInputWarehouse(), "door")); list.add(getWareHouse(work.getInputWarehouse(), "roof")); return list; } private Warehouse getWareHouse(Warehouse inputWarehouse, String stepClass) { Warehouse warehouse = new WarehouseDefault(); warehouse.put("class", stepClass); warehouse.putSubWarehouse(inputWarehouse); return warehouse; } } |
从上面能够看到,第三部构建了4个门仓库一个车顶仓库,相同的,能够让4个工人同一时候装门。
上面就把全部的准备工作都做好了,接下来就是測试方法了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { JobCenter jobCenter = new JobCenterLocal(); for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepFirstWorker()); } for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepSecondTyreWorker()); } for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepSecondSeatWorker()); } for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepSecondEngineWorker()); } for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepThirdDoorWorker()); } for (int i = 0; i < 5; i++) { jobCenter.registerWorker(new StepThirdRoofWorker()); } jobCenter.registerForeman(new ForemanSelectOneWorker("first")); <span></span> <span></span>jobCenter.registerForeman(new ForemanSelectAllWorker("second", new SecondWorkSplitter())); jobCenter.registerForeman(new ForemanSelectAllWorker("third",new ThirdWorkSplitter())); Warehouse inputWarehouse = new WarehouseDefault(); inputWarehouse.put("class", "car"); inputWarehouse.put("carType", "普桑"); WorkDefault work = new WorkDefault("first", inputWarehouse); work.setForemanType("first"); WorkDefault work2 = new WorkDefault("second"); work2.setForemanType("second"); WorkDefault work3 = new WorkDefault("third"); work3.setForemanType("third"); work.setNextWork(work2).setNextWork(work3); Warehouse warehouse = jobCenter.doWork(work); jobCenter.stop(); } } |
呵呵,工人各加了5个。然后注冊了三个工头,第一步的工头是随便挑一个工人类型的。第二步和第三步是挑全部工人的。同一时候还指定了任务分解器。
接下来就构建了一个工作。造一个高端大气上档次的普桑汽车。然后告诉职业介绍所说给我造就能够了。
以下是造车的过程,我把日志也贴上来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
普桑 构建底盘完毕. -234 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:4af96b81d14a4954a6b649308d444e4c,type:second>执行開始,线程数9... -234 [id:4af96b81d14a4954a6b649308d444e4c,type:second-a763f156ffd74b5db285198d2498edcf] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-a763f156ffd74b5db285198d2498edcf>执行開始... -234 [id:4af96b81d14a4954a6b649308d444e4c,type:second-c2d2fb38ef6c4509b3a39b3e7d5c1d61] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-c2d2fb38ef6c4509b3a39b3e7d5c1d61>执行開始... -234 [id:4af96b81d14a4954a6b649308d444e4c,type:second-d624ea0a6df3409c80df6b97ab3c813b] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-d624ea0a6df3409c80df6b97ab3c813b>执行開始... -235 [id:4af96b81d14a4954a6b649308d444e4c,type:second-abdb57f0641a4727a9efa744d07cf2d1] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-abdb57f0641a4727a9efa744d07cf2d1>执行開始... -236 [id:4af96b81d14a4954a6b649308d444e4c,type:second-d6f7074f6c4a4b12bd37ec5f5c11aff8] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-d6f7074f6c4a4b12bd37ec5f5c11aff8>执行開始... -237 [id:4af96b81d14a4954a6b649308d444e4c,type:second-04db3f945b804500a2bbe2b9aabdce3b] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-04db3f945b804500a2bbe2b9aabdce3b>执行開始... Base:something about baseInfo engine is Ok Base:something about baseInfo seat is Ok -245 [id:4af96b81d14a4954a6b649308d444e4c,type:second-a763f156ffd74b5db285198d2498edcf] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-a763f156ffd74b5db285198d2498edcf>执行结束 -246 [id:4af96b81d14a4954a6b649308d444e4c,type:second-f3efba2dc7804c6cbcd5a25f42fdc177] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-f3efba2dc7804c6cbcd5a25f42fdc177>执行開始... -246 [id:4af96b81d14a4954a6b649308d444e4c,type:second-abdb57f0641a4727a9efa744d07cf2d1] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-abdb57f0641a4727a9efa744d07cf2d1>执行结束 Base:something about baseInfo seat is Ok -248 [id:4af96b81d14a4954a6b649308d444e4c,type:second-8c3b9359bcfa4de7b6e0492daab0d73a] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-8c3b9359bcfa4de7b6e0492daab0d73a>执行開始... Base:something about baseInfo tyre is Ok -250 [id:4af96b81d14a4954a6b649308d444e4c,type:second-f3efba2dc7804c6cbcd5a25f42fdc177] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-f3efba2dc7804c6cbcd5a25f42fdc177>执行结束 -250 [id:4af96b81d14a4954a6b649308d444e4c,type:second-c2d2fb38ef6c4509b3a39b3e7d5c1d61] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-c2d2fb38ef6c4509b3a39b3e7d5c1d61>执行结束 Base:something about baseInfo seat is Ok -252 [id:4af96b81d14a4954a6b649308d444e4c,type:second-869b573e226046aca8ad30765f1f300c] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-869b573e226046aca8ad30765f1f300c>执行開始... -253 [id:4af96b81d14a4954a6b649308d444e4c,type:second-8c3b9359bcfa4de7b6e0492daab0d73a] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-8c3b9359bcfa4de7b6e0492daab0d73a>执行结束 Base:something about baseInfo seat is Ok Base:something about baseInfo tyre is Ok -257 [id:4af96b81d14a4954a6b649308d444e4c,type:second-d624ea0a6df3409c80df6b97ab3c813b] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-d624ea0a6df3409c80df6b97ab3c813b>执行结束 -258 [id:4af96b81d14a4954a6b649308d444e4c,type:second-04db3f945b804500a2bbe2b9aabdce3b] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-04db3f945b804500a2bbe2b9aabdce3b>执行结束 Base:something about baseInfo tyre is Ok Base:something about baseInfo tyre is Ok -262 [id:4af96b81d14a4954a6b649308d444e4c,type:second-869b573e226046aca8ad30765f1f300c] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-869b573e226046aca8ad30765f1f300c>执行结束 -264 [id:4af96b81d14a4954a6b649308d444e4c,type:second-d6f7074f6c4a4b12bd37ec5f5c11aff8] INFO - 线程<id:4af96b81d14a4954a6b649308d444e4c,type:second-d6f7074f6c4a4b12bd37ec5f5c11aff8>执行结束 -264 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:4af96b81d14a4954a6b649308d444e4c,type:second>执行结束, 用时:30ms -333 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third>执行開始,线程数5... -334 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-ca58e9b733514c668a224875417c9d26] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-ca58e9b733514c668a224875417c9d26>执行開始... -334 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-17debef817e34c49996a2c38840f3de2] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-17debef817e34c49996a2c38840f3de2>执行開始... -334 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-af0e914cce89480987c6184a885770d5] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-af0e914cce89480987c6184a885770d5>执行開始... -334 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-3f7707cb2a224d3d8844a09271b24a07] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-3f7707cb2a224d3d8844a09271b24a07>执行開始... Base:something about baseInfo door is Ok Base:something about baseInfo door is Ok Base:something about baseInfo -338 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-ca58e9b733514c668a224875417c9d26] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-ca58e9b733514c668a224875417c9d26>执行结束 door is Ok -339 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-cfccfb37ebda4279b7552f7e060b2ddb] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-cfccfb37ebda4279b7552f7e060b2ddb>执行開始... -338 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-17debef817e34c49996a2c38840f3de2] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-17debef817e34c49996a2c38840f3de2>执行结束 Base:something about baseInfo door is Ok Base:something about baseInfo -340 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-3f7707cb2a224d3d8844a09271b24a07] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-3f7707cb2a224d3d8844a09271b24a07>执行结束 roof is Ok -340 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-af0e914cce89480987c6184a885770d5] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-af0e914cce89480987c6184a885770d5>执行结束 -342 [id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-cfccfb37ebda4279b7552f7e060b2ddb] INFO - 线程<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third-cfccfb37ebda4279b7552f7e060b2ddb>执行结束 -343 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third>执行结束, 用时:10ms |
从上面的日志能够看出:
因为第一步工作是挑一个单干的,因此是没有启用线程组的
第二步同一时候有9个线程干活:
1 2 3 |
-234 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:4af96b81d14a4954a6b649308d444e4c,type:second>执行開始,线程数9... ... -264 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:4af96b81d14a4954a6b649308d444e4c,type:second>执行结束, 用时:30ms |
第三步同一时候有5个线程干活:
1 2 3 |
-333 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third>执行開始,线程数5... ... -343 [RMI TCP Connection(1)-192.168.84.73] INFO - 线程组<id:9b0de678632d4fb8b87ae9db4b6436f8,type:third>执行结束, 用时:10ms |
总结:
Tiny并行计算框架确实是能够方便的解决各种复杂并行计算的问题。
Tiny并行计算框架之复杂演示样例的更多相关文章
- java并行调度框架封装及演示样例
參考资料: 阿里巴巴开源项目 CobarClient 源代码实现. 分享作者:闫建忠 分享时间:2014年5月7日 ---------------------------------------- ...
- Python Web框架Tornado的异步处理代码演示样例
1. What is Tornado Tornado是一个轻量级但高性能的Python web框架,与还有一个流行的Python web框架Django相比.tornado不提供操作数据库的ORM接口 ...
- android listview综合使用演示样例_结合数据库操作和listitem单击长按等事件处理
本演示样例说明: 1.自己定义listview条目样式,自己定义listview显示列数的多少,灵活与数据库中字段绑定. 2.实现对DB的增删改查,而且操作后listview自己主动刷新. 3.响应用 ...
- Thrift的安装和简单演示样例
本文仅仅是简单的解说Thrift开源框架的安装和简单使用演示样例.对于具体的解说,后面在进行阐述. Thrift简述 ...
- [hadoop系列]Pig的安装和简单演示样例
inkfish原创,请勿商业性质转载,转载请注明来源(http://blog.csdn.net/inkfish ).(来源:http://blog.csdn.net/inkfish) Pig是Yaho ...
- SNF快速开发平台MVC-各种级联绑定方式,演示样例程序(包含表单和表格控件)
做了这么多项目,经常会使用到级联.联动的情况. 如:省.市.县.区.一级分类.二级分类.三级分类.仓库.货位. 方式:有表单需要做级联的,还是表格行上需要做级联操作的. 实现:实现方法也有很多种方式. ...
- 通过Canvas及File API缩放并上传图片完整演示样例
创建一个只管的用户界面,并同意你控制图片的大小.上传到server端的数据,并不须要处理enctype为 multi-part/form-data 的情况.只一个简单的POST表单处理程序就能够了. ...
- 01_MUI之Boilerplate中:HTML5演示样例,动态组件,自己定义字体演示样例,自己定义字体演示样例,图标字体演示样例
1安装HBuilder5.0.0,安装后的界面截图例如以下: 2 依照https://www.muicss.com/docs/v1/css-js/boilerplate-html中的说明,创建上 ...
- 移动端报表JS开发演示样例
近期对移动端的报表开发颇有研究,细磨精算了好久,尽管到如今还是"囊中羞涩",但决定还是先抛砖引玉,拿点小干货出来和大家分享. 研究的工具是比較有代表性的FineReport. 1. ...
随机推荐
- em换算px
一般浏览器默认的1em=16px,所以常用字体大小如下: 10px=0.625em 12px=0.75em 14px=0.875em 16px=1em 18px=1.125em 20px=1.25em ...
- Linux入门:文件权限、用户、用户组(比较清楚)
单个文件名或目录名长度不超过255字符: 文件或目录的绝对路径长度不超过4096字符: 一.文件所有者与用户组 一个文件有很多属性,包括文件类型.文件权限.文件隐藏权限.文件所有者.用户组 ...
- Java的LockSupport.park()实现分析
LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了主要的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,仅仅有两个函数: ...
- javascript函数的声明,及返回值
<1> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>< ...
- JS firebug小技巧
实际上前端的发展与进步也离不开浏览器的支持,而对于开发者来讲,浏览器最好的支持,就是对于debug的良好支持,甚至在某些兴许接手的项目中,前端的debug甚至能够解决好多问题--不说了,都是泪啊!还是 ...
- google2013校园招聘笔试题(全国)
google2013校园招聘笔试题 1. 单项选择题1.1如果把传输速率定义为单位时间内传送的信息量(以字节计算)多少.关于一下几种典型的数据传输速率:1.使用USB2.0闪存盘,往USB闪存盘上拷贝 ...
- 关于new enhancement的一些知识
关于new enhancement sap源程序里也给我们留了很多. 以下例句point .section.spot说明这些知识点. 1.不管是point还是section 都是基于spot的,spo ...
- RS100项目进展更新
1. 添加手机界面访问网页,毕竟PDA的屏幕大小和PC机大小不一致,完成了一自适应网页,便于在手机上观看实时画面: 2. 此项目为一个远程视频监控+远程开关项目,远程PC机或者手机能操作到监控端的开关 ...
- js模板引擎--artTemplate
js模板引擎--artTemplate 以前研究过一段时间的handlebars,但因为其渲染性能略逊于腾讯的artTemplate(在artTemplate的GitHub官网上有推荐的性能测试地址) ...
- Android高手进阶——Adapter深入理解与优化
Android高手进阶--Adapter深入理解与优化 通常是针对包括多个元素的View,如ListView,GridView.ExpandableListview,的时候我们是给其设置一个Adapt ...