- 浏览: 72729 次
- 性别:
- 来自: 北京
最新评论
-
zq3062211015:
想法很好。。万一 c就一个人下车 b很浪费啊
java并发学习之三:非阻塞漫想,关于环岛与地铁 -
zq3062211015:
楼主是大神,膜拜啊,不过有个地方说的不太对啊, if (poo ...
java并发学习之二:线程池(五) -
snake1987:
milk_36 写道终于找到是用java的了!LZ想问一下你们 ...
关于社交游戏中的同步服务器(长连接服务器) -
milk_36:
终于找到是用java的了!LZ想问一下你们项目中protobu ...
关于社交游戏中的同步服务器(长连接服务器) -
hobitton:
额,是我说的不准确哈,server不仅仅是options的集合 ...
java并发学习之二:线程池(四)
最近换了一个公司,确切来说应该是进入了一个新的行业,很多东西的学习都是从0开始的,学的东西很多很杂,先分点记下,以便以后复习回忆或者近一步学习
1.key-value数据库
像redis,memcached都是这样的数据库,网上有一篇小日本的文章,写得很详细很好,虽然是小日本的,但也只能将就一下了
memcached全面剖析系列
再说一下学习中了解到它的一些特点(可能有些不准确的地方):
1.它像一个大map,所有的内容都是键值对
2.它的所有内容都是放内存中的,但可以用其他的辅助手段做持久化
3.因为是操作内存的,而且只有纯粹的操作,没有任何额外的过程(像sql的编译),所以它很快,快得难以想象,但这个快是以牺牲很多其他的东西为代价的
4.它难以维护,它没有图形化操作工具,这也很容易理解,像我们想去像维护sql数据库一样维护一个map,你能有什么好办法吗?
5.没有数据完整性之类的概念,所有逻辑上的关联都是人为地去维护的,所以让它更进一步难以维护。
6.因为它的所有数据都放在内存中的,所以数据库服务器崩溃对数据的影响几乎是致命的(即使你使用了一些持久化的办法)
7.它也算个新生的东西,所以很多东西很不完善,像memcached的协议还是只有文本形式的,二进制协议正在制定中。
8.memcached集群默认中的一致性hash的用的是一个圆圈形的连续的hash值,服务器对应的hash值一般是不连续的,动态增减服务器会变得很方便。具体可以看小日本的文章
9.数据库服务器的主要硬件消耗是内存,而非cpu,小日本的文章也说了,cpu使用率几乎为0
10.它与sql数据库的区别也是很明显的,它更注重的是简单而高效。
近日用这种数据库进行了一些开发,也获得了一些经验和收获
1.虽然数据库没有提供主键外键这样一些的关联,但事实上是需要的,这时我们会人为的去维护这样一个关系,如存入一个对象,对象中带着一个list,这个list中可以索引到另外的一些key值,我们人为地使用一些原子操作去维护他们之前的关系(可以看到它的不稳健性),实质上是将数据库的一些工作由我们人为地去维护了。
2.在分布式的架构中,对整个应用的同步操作可以通过数据库来做,在思考模式上,与传统的单机上的并发是完全不一样的。
举个例子:
像我们经常使用的一个cas操作,在分布式的同步中,是不推荐的,因为对于单机,get,cas都是对内存(或者说是对cpu)的一个操作,效率是很高效,但对于远程数据库而言,他就是2个远程访问了,上述的一个操作是会大大增加io的压力的(尤其是冲突域相对较大,对这个原子变量的修改频繁的情况更是明显)。
所以在分布式的同步中,能用append,add这样的原子操作会更好
另一点是精确模型和不精确模型(现在只是有一些感觉,其实理解还是不深刻,之后需要找点书来学习一下),举个例子,对于key-value数据库,我们存了一个整形列表,列表里面的内容是我们需要的一些数据,如果是需求精确模型的,我们需要用cas进行插入或者删除操作,如果是不精确模型,我们可能只是进行append,而不去计较是否重复等,某个时候做一个整体判断,然后set
如果不是需求很明确地要求精确,不精确模型会大大减轻数据库的压力(这也让我对之前学习并发的时候的一些想法发生了巨大的改变,因为在实际应用中,不是都必须要求绝对准确的,像incre,某些时候,我们不要求它一定会增加了1,甚至减少我们也是允许的)
3.memcached的cas用的是乐观锁,也就是通过一个版本号来进行的
4.锁操作可以通过一个add或者remove,cas来进行,但像锁的await和notify动作就无法实现了,只能通过客户端的轮训来做,这个锁的值如果是一个时间戳会有很多好处,如某个锁操作进行了,但没有释放服务器就崩溃了,我们这时可以判断这个时间戳到当前时间的时间差,如果远远超过了可能锁住的时间,我们就帮他解锁
2.protobuf
公司用了protobuf,在日常工作中都有所接触,一直没有时间做一些深入一点的探究,今天忙中偷闲,深入理解了一下,以下是个人的一些的总结,如果有遗漏或者错误的地方,还请看到的tx斧正
2.1.protobuf的功能
protobuf是一个google开发的开源工具,作用正如主页上说的:serialize and retrieve structured data
说白了,其实它的功能跟java的序列化和反序列化是一样的,只不过更强大,更有效率
但是在日常使用中,还会遇到这样几个问题:
a.数据结构的增删改查对之前的数据的是否会有影响,也就是版本兼容性
b.数据的压缩比率
c.易用性
d.性能
下文主要就逐步围绕这几方面进行进一步的探究
2.2.怎么用protobuf?(简单提一下)
a.按照说明编写一个.proto文件
b.用google提供的编译工具进行编译
这样,一个专负责序列化和反序列化的类就生成了,然后你可以直接去调用这个类进行序列化和反序列化了
2.3.protobuf支持的数据类型和编码
其实有用的也就4种,变长的,int32,int64和长度不限制“Length-delimited”
对于java来说,一般用的也就8种数据类型而已
下面开始对java的每种数据类型进行进一步的分析(为了方便懒得看google文档的tx,这里也稍微翻译一下)
稍微写了段测试代码
下面是proto文件的内容,上面的java代码引用的是编译后的代码
根据文档所说的,varint的编码规则是(field_number << 3) | wire_type,
而value部分的编码则是用的是很多协议都一样的:首bit表示后面是否还有内容,后7位才是有效位
单单一个bool,输出结果是18:01,0001 1000 0000 0001,
field_number = 3,wire_type = 0,第一个byte就出来了,然后是第二个,没什么问题
一个long+一个bool,输出是10:d7:08:18:01
可以看到编码是相邻着的,没有任何的间隔,而根据协议,在解码时也可以很简单地还原为各数据类型的有效数据(即使没有.proto编译出来的文件,也就是说使用抓包工具进行直接报文分析是可以的,如果有时间,再练练手去,但到底有没有价值呢?还待商榷)
然后进一步往后推,protobuf在做版本兼容的时候,会怎么做呢?
增:增加的时候,只有读之前的数据需要处理,如果我自己来实现,先是将整个报文进行分析,解码成具体类型的一个个值,还有他们的序号,然后对号入座,发现没有的,就给他一个默认值,很简单
删:这也很简单,也就是发现不需要的,直接丢弃就ok了,而之前的数据也不会占空间,因为当我们读取后再次存取的时候,这些数据也同时清空了,唯一只有个要求:该索引不能重用
改:改其实相当于增跟删的结合,举个例子:一个数据一开始是int,现在需要改成long,但数据需要保留,
很简单,在.proto中删除旧的int,加入新的long(注意,索引不能重用),读的时候还是按正常,当拿到解码后的数据,先看一下原索引的值是否为空,不为空,则读取并放入新的数据类型中,存的时候则按正常的逻辑就可以了,这样,.proto中的东西就可以删掉了
当然,以上的东西都是猜的,google应该也是这样做的吧?
在api中找到了这样的api:getUnknownFields().getField(4).getVarintList();
有点像了,再试试
看代码
果然拿到了没定义的数据
根据编码规则,很容易看出该协议的压缩算法只是到byte级的,也没有long,int,short之类的概念,对于bool这样的,就有点浪费了(之后再看看package是怎么编码的)
而对于int,short之类的,压缩比率也不大(起码没预料中的高效,因为一直认为谷歌是神一样的存在),值在0-127之前的,才是2个byte(一个作为索引和类型,一个存储值),再往上加,就需要更多的空间了,除了头个byte之外,后面的byte利用率也只有7/8,跟之前练手做的snmp协议是一样的
接下来是package了,对单个参数无所谓,但对于数组这样的,总可以优化吧
继续测试
很失望~真的没做压缩,只是按照文档所说的,当成了“Length-delimited”,然后再进行编码,结果如下:
0a:04:01:00:00:01
把package去掉看看?
08:01:08:00:08:00:08:01
完全按单个的形式来编码的~~
至此,protobuf已基本明晰了,包括一些细节,如
enum:按varint编码
repeat非package:当成“Length-delimited”,再按varint进行编码
只是repeat:按正常编码,然后用同一个索引
总的来说,对文档的解读算是全部明晰了,但对google的神话也有点失望
再看看易用性
protobuf生成的类其实就是一个DTO,因为它是由编译生成的,所以为了以后扩展方便,我们不能修改它,这样想使用它就有两种方式(如果你之前设计中没有DTO的概念),一种是继承它(缺点是代码后期会稍微有点乱),一种是做一次拷贝(条理较为清晰,但效率上显然会稍慢,毕竟多一次对象拷贝的过程)
如果本身就有DTO,那就简单了,只需要替换DTO就ok了
3.java与c的对接
1.c的char是一个byte的,但java的是两个
2.c中对多个byte的数据类型的编码会根据环境的不同而不同,java则默认就是网络序,而网络序就是我们正常的读取习惯(这个序特别容易搞乱,尤其是自己code的时候,建议写单元测试用ByteBuffer进行验证一下)
1.key-value数据库
像redis,memcached都是这样的数据库,网上有一篇小日本的文章,写得很详细很好,虽然是小日本的,但也只能将就一下了
memcached全面剖析系列
再说一下学习中了解到它的一些特点(可能有些不准确的地方):
1.它像一个大map,所有的内容都是键值对
2.它的所有内容都是放内存中的,但可以用其他的辅助手段做持久化
3.因为是操作内存的,而且只有纯粹的操作,没有任何额外的过程(像sql的编译),所以它很快,快得难以想象,但这个快是以牺牲很多其他的东西为代价的
4.它难以维护,它没有图形化操作工具,这也很容易理解,像我们想去像维护sql数据库一样维护一个map,你能有什么好办法吗?
5.没有数据完整性之类的概念,所有逻辑上的关联都是人为地去维护的,所以让它更进一步难以维护。
6.因为它的所有数据都放在内存中的,所以数据库服务器崩溃对数据的影响几乎是致命的(即使你使用了一些持久化的办法)
7.它也算个新生的东西,所以很多东西很不完善,像memcached的协议还是只有文本形式的,二进制协议正在制定中。
8.memcached集群默认中的一致性hash的用的是一个圆圈形的连续的hash值,服务器对应的hash值一般是不连续的,动态增减服务器会变得很方便。具体可以看小日本的文章
9.数据库服务器的主要硬件消耗是内存,而非cpu,小日本的文章也说了,cpu使用率几乎为0
10.它与sql数据库的区别也是很明显的,它更注重的是简单而高效。
近日用这种数据库进行了一些开发,也获得了一些经验和收获
1.虽然数据库没有提供主键外键这样一些的关联,但事实上是需要的,这时我们会人为的去维护这样一个关系,如存入一个对象,对象中带着一个list,这个list中可以索引到另外的一些key值,我们人为地使用一些原子操作去维护他们之前的关系(可以看到它的不稳健性),实质上是将数据库的一些工作由我们人为地去维护了。
2.在分布式的架构中,对整个应用的同步操作可以通过数据库来做,在思考模式上,与传统的单机上的并发是完全不一样的。
举个例子:
for(;;) { int expect = atomicInteger.get(); if(atomicInteger.cas(expect,expect+1)) break; }
像我们经常使用的一个cas操作,在分布式的同步中,是不推荐的,因为对于单机,get,cas都是对内存(或者说是对cpu)的一个操作,效率是很高效,但对于远程数据库而言,他就是2个远程访问了,上述的一个操作是会大大增加io的压力的(尤其是冲突域相对较大,对这个原子变量的修改频繁的情况更是明显)。
所以在分布式的同步中,能用append,add这样的原子操作会更好
另一点是精确模型和不精确模型(现在只是有一些感觉,其实理解还是不深刻,之后需要找点书来学习一下),举个例子,对于key-value数据库,我们存了一个整形列表,列表里面的内容是我们需要的一些数据,如果是需求精确模型的,我们需要用cas进行插入或者删除操作,如果是不精确模型,我们可能只是进行append,而不去计较是否重复等,某个时候做一个整体判断,然后set
如果不是需求很明确地要求精确,不精确模型会大大减轻数据库的压力(这也让我对之前学习并发的时候的一些想法发生了巨大的改变,因为在实际应用中,不是都必须要求绝对准确的,像incre,某些时候,我们不要求它一定会增加了1,甚至减少我们也是允许的)
3.memcached的cas用的是乐观锁,也就是通过一个版本号来进行的
4.锁操作可以通过一个add或者remove,cas来进行,但像锁的await和notify动作就无法实现了,只能通过客户端的轮训来做,这个锁的值如果是一个时间戳会有很多好处,如某个锁操作进行了,但没有释放服务器就崩溃了,我们这时可以判断这个时间戳到当前时间的时间差,如果远远超过了可能锁住的时间,我们就帮他解锁
2.protobuf
公司用了protobuf,在日常工作中都有所接触,一直没有时间做一些深入一点的探究,今天忙中偷闲,深入理解了一下,以下是个人的一些的总结,如果有遗漏或者错误的地方,还请看到的tx斧正
2.1.protobuf的功能
protobuf是一个google开发的开源工具,作用正如主页上说的:serialize and retrieve structured data
说白了,其实它的功能跟java的序列化和反序列化是一样的,只不过更强大,更有效率
但是在日常使用中,还会遇到这样几个问题:
a.数据结构的增删改查对之前的数据的是否会有影响,也就是版本兼容性
b.数据的压缩比率
c.易用性
d.性能
下文主要就逐步围绕这几方面进行进一步的探究
2.2.怎么用protobuf?(简单提一下)
a.按照说明编写一个.proto文件
b.用google提供的编译工具进行编译
这样,一个专负责序列化和反序列化的类就生成了,然后你可以直接去调用这个类进行序列化和反序列化了
2.3.protobuf支持的数据类型和编码
其实有用的也就4种,变长的,int32,int64和长度不限制“Length-delimited”
对于java来说,一般用的也就8种数据类型而已
下面开始对java的每种数据类型进行进一步的分析(为了方便懒得看google文档的tx,这里也稍微翻译一下)
稍微写了段测试代码
public class Student { public static void main(String[] args) { StudentProtoBuf.Student.Builder studentProtoBuf = StudentProtoBuf.Student.newBuilder(); //studentProtoBuf.setId(1111); //studentProtoBuf.setName("test"); studentProtoBuf.setSex(true); byte[] bytes = studentProtoBuf.build().toByteArray(); StringBuilder builder = new StringBuilder(); for(byte b : bytes) { builder.append(parseToString(b)); builder.append(":"); } System.out.println(builder.toString()); } public static String parseToString(byte b) { int result = b & 0xff; String resutString = Integer.toHexString(result); return resutString.length() == 1 ? "0" + resutString : resutString; } }
下面是proto文件的内容,上面的java代码引用的是编译后的代码
package tutorial; option java_package = "com.hoolai.protobuf.test"; option java_outer_classname = "StudentProtoBuf"; message Student { optional string name = 1; optional int64 id = 2; optional bool sex = 3; }
根据文档所说的,varint的编码规则是(field_number << 3) | wire_type,
而value部分的编码则是用的是很多协议都一样的:首bit表示后面是否还有内容,后7位才是有效位
单单一个bool,输出结果是18:01,0001 1000 0000 0001,
field_number = 3,wire_type = 0,第一个byte就出来了,然后是第二个,没什么问题
一个long+一个bool,输出是10:d7:08:18:01
可以看到编码是相邻着的,没有任何的间隔,而根据协议,在解码时也可以很简单地还原为各数据类型的有效数据(即使没有.proto编译出来的文件,也就是说使用抓包工具进行直接报文分析是可以的,如果有时间,再练练手去,但到底有没有价值呢?还待商榷)
然后进一步往后推,protobuf在做版本兼容的时候,会怎么做呢?
增:增加的时候,只有读之前的数据需要处理,如果我自己来实现,先是将整个报文进行分析,解码成具体类型的一个个值,还有他们的序号,然后对号入座,发现没有的,就给他一个默认值,很简单
删:这也很简单,也就是发现不需要的,直接丢弃就ok了,而之前的数据也不会占空间,因为当我们读取后再次存取的时候,这些数据也同时清空了,唯一只有个要求:该索引不能重用
改:改其实相当于增跟删的结合,举个例子:一个数据一开始是int,现在需要改成long,但数据需要保留,
很简单,在.proto中删除旧的int,加入新的long(注意,索引不能重用),读的时候还是按正常,当拿到解码后的数据,先看一下原索引的值是否为空,不为空,则读取并放入新的数据类型中,存的时候则按正常的逻辑就可以了,这样,.proto中的东西就可以删掉了
当然,以上的东西都是猜的,google应该也是这样做的吧?
在api中找到了这样的api:getUnknownFields().getField(4).getVarintList();
有点像了,再试试
看代码
byte[] result = {0x0a,0x04,0x74,0x65,0x73,0x74,0x10,(byte) 0xd7,0x08,0x18,0x01,0x20,0x01};//之前的代码System.out出来的,后面加了,0x20,0x01,意思是序号为第四的,用varint编码,并且值为1 com.hoolai.protobuf.test.StudentProtoBuf.Student student = StudentProtoBuf.Student.parseFrom(result); student.getUnknownFields().getField(4).getVarintList(); System.out.println(student);
果然拿到了没定义的数据
根据编码规则,很容易看出该协议的压缩算法只是到byte级的,也没有long,int,short之类的概念,对于bool这样的,就有点浪费了(之后再看看package是怎么编码的)
而对于int,short之类的,压缩比率也不大(起码没预料中的高效,因为一直认为谷歌是神一样的存在),值在0-127之前的,才是2个byte(一个作为索引和类型,一个存储值),再往上加,就需要更多的空间了,除了头个byte之外,后面的byte利用率也只有7/8,跟之前练手做的snmp协议是一样的
接下来是package了,对单个参数无所谓,但对于数组这样的,总可以优化吧
继续测试
package tutorial; option java_package = "com.hoolai.protobuf.test"; option java_outer_classname = "StudentProtoBuf"; message Student { repeated bool sex = 1 [packed=true]; repeated int32 id = 2 [packed=true]; }
public static void main(String[] args) throws InvalidProtocolBufferException { StudentProtoBuf.Student.Builder studentProtoBuf = StudentProtoBuf.Student.newBuilder(); studentProtoBuf.addSex(true); studentProtoBuf.addSex(false); studentProtoBuf.addSex(false); studentProtoBuf.addSex(true); byte[] bytes = studentProtoBuf.build().toByteArray(); StringBuilder builder = new StringBuilder(); for(byte b : bytes) { builder.append(parseToString(b)); builder.append(":"); } System.out.println(builder.toString()); } public static String parseToString(byte b) { int result = b & 0xff; String resutString = Integer.toHexString(result); return resutString.length() == 1 ? "0" + resutString : resutString; }
很失望~真的没做压缩,只是按照文档所说的,当成了“Length-delimited”,然后再进行编码,结果如下:
0a:04:01:00:00:01
把package去掉看看?
08:01:08:00:08:00:08:01
完全按单个的形式来编码的~~
至此,protobuf已基本明晰了,包括一些细节,如
enum:按varint编码
repeat非package:当成“Length-delimited”,再按varint进行编码
只是repeat:按正常编码,然后用同一个索引
总的来说,对文档的解读算是全部明晰了,但对google的神话也有点失望
再看看易用性
protobuf生成的类其实就是一个DTO,因为它是由编译生成的,所以为了以后扩展方便,我们不能修改它,这样想使用它就有两种方式(如果你之前设计中没有DTO的概念),一种是继承它(缺点是代码后期会稍微有点乱),一种是做一次拷贝(条理较为清晰,但效率上显然会稍慢,毕竟多一次对象拷贝的过程)
如果本身就有DTO,那就简单了,只需要替换DTO就ok了
3.java与c的对接
1.c的char是一个byte的,但java的是两个
2.c中对多个byte的数据类型的编码会根据环境的不同而不同,java则默认就是网络序,而网络序就是我们正常的读取习惯(这个序特别容易搞乱,尤其是自己code的时候,建议写单元测试用ByteBuffer进行验证一下)
发表评论
-
关于jdk7的aio
2012-11-28 13:59 0最近耳边老有人提jdk7的 ... -
关于锁的两个小技巧
2012-09-03 14:55 1392现在我们的开发中越来越多用锁的情况,锁其实比cas恐怖很多,像 ... -
关于java hotspot vm的server版和client版的一点小事
2012-09-03 14:53 4115我们知道,java的虚拟器其实是有两个版本的, client ... -
关于游戏脚本
2012-09-03 14:43 2241社交游戏其实不是太需 ... -
关于社交游戏中的同步服务器(长连接服务器)
2012-09-03 14:39 7510博客好久没打理了,今 ... -
关于游戏中的同步服务器(长连接服务器)
2012-09-03 14:33 1博客好久没打理了,今 ... -
BTrace实践
2011-10-13 15:30 0一直都在关注java的profile工具,这几天发现了这个好东 ... -
项目回忆(一):虚拟房间系统
2011-09-23 14:34 1425需求: 1.硬件环境:所有 ... -
近月学习记录(四)
2011-09-12 12:48 0基于netty的同步游戏服 ... -
近月学习记录(三)
2011-09-10 15:01 0最近在用netty做一个交 ... -
protobuf深入分析
2011-07-22 19:31 0公司用了protobuf,在日常工作中都有所接触,一直没有时间 ... -
近月学习记录(二)
2011-06-12 22:30 01.maven maven其实不难,但是一开始学习的时候的确感 ... -
java并发学习之二:线程池(五)
2011-04-17 13:31 2662之前的线程池已实现了基本的功能:运行每一个线程,而且测试了一下 ... -
java并发学习之六:JCSP(Java Communicating Sequential Processes)实践
2011-04-13 11:32 5851首先得描述下什么是JCSP ... -
java并发学习之二:线程池(四)
2011-04-12 17:43 2385一直都知道有两个jvm,一个是server,一个是client ... -
java并发学习之二:线程池(三)
2011-04-08 16:24 2251没找到什么好工具,也没得到好建议,好技巧,只能自己摸索了 一 ... -
java并发学习之五:读JSR133笔记
2011-04-06 11:33 10899在写线程池的时候,遇到了很多的问题,特别是happen-bef ... -
java并发学习之四:JSR 133 (Java Memory Model) FAQ【译】
2011-04-01 16:52 4083Jsr133地址:http://www.c ... -
java并发学习之三:非阻塞漫想,关于环岛与地铁
2011-03-27 21:10 1810到过北京上地的都会知道,上地城铁往西走有一个很大的上地环岛,旁 ... -
java并发学习之二:线程池(二)
2011-03-24 09:43 2327在看书的时候看到了一个观察死锁的工具TDA(Thread Du ...
相关推荐
近些日学习一下ruby方面的,顺便看看java方面的, 这个是Java JDK6的学习笔记电子版, 压缩包里包含两个文件, 一个是chm格式(这个还行吧),当然如果你喜欢PDF,你可使用ABC Amber CHM Converter转换一下就可以了,...
整理者黄海广对课程笔记的更新和维护付出了巨大的努力,从2014年12月至今,课程文档经过了多次修改和更新,内容从最初的介绍到加入了线性代数的复习,再到之后的多变量线性回归等内容,体现了对机器学习课程内容的...
Sketchup 8.0是一个功能强大且灵活的3D模型设计软件,本笔记记录了Sketchup 8.0的基础操作和技巧,旨在帮助初学者快速掌握Sketchup 8.0的使用。 视图操作: 1. 环绕观察:点击环绕观察按钮,可以观察模型。小技巧...
SATA学习笔记 SATA(Serial Advanced Technology Attachment)是一种高速串行接口技术,用于连接计算机和存储设备,如硬盘、固态硬盘、U盘等。下面是SATA学习笔记的详细知识点: 硬盘基本概念 硬盘是计算机系统的...
由于提供的压缩包文件列表只有一个文件名"ahao2",无法确定具体笔记内容,以上都是基于书名和描述的常规NLP学习路径。实际笔记可能包含这些主题的详细解析、代码示例和实践经验,对于初学者来说是非常宝贵的参考资料...
为提高读者学习效率,本书提供了21章的配书视频教程及近300个实例的源代码。这些宝贵的学习资源有助于读者迅速入门,动手开发实践。 本书既适合作为C#完全自学图书,也适合作为相关培训机构的培训教材或者高校...
本人近半年自学python 方面全套的学习笔记。人生苦短,我用python。包含web、前端、django、flask、机器学习、深度学习、数据分析,还有常用如mysql、redis数据库相关材料
为提高读者学习效率,本书提供了21章的配书视频教程及近300个实例的源代码。这些宝贵的学习资源有助于读者迅速入门,动手开发实践。 本书既适合作为C#完全自学图书,也适合作为相关培训机构的培训教材或者高校...
1、包括网工第五版较全面的学习笔记(近4万字)、常用检测命令实践图、协议神图、常见编码图、网工简单的100条知识点 2、笔记目录如: 第一章 计算机基础知识 一、数据表示 (一) 定点和浮点和整数 二、逻辑计算机 ...
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...
本资源是关于一年级语文下册的“培优补差”记录表,旨在帮助学生弥补语文学习中的差距,并提高语文能力。该记录表涵盖了多个方面的内容,包括汉字的笔画数、形近字的辨析、汉字结构、部首和偏旁、查字典方法等。 ...
本笔记基于林子雨老师在MOOC上的《大数据技术原理》课程,旨在为IT从业者和大学生提供一个全面了解大数据的基础框架。 首先,我们要认识到大数据的发展背景。随着互联网的普及,以及物联网、社交媒体、移动设备等...
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...
数据结构与算法学习笔记 本文档概括了数据结构和算法...本文档为读者提供了一个系统的数据结构和算法学习笔记,涵盖了堆、线索化二叉树、赫夫曼树等重要概念。读者可以通过学习本文档来掌握这些重要的数据结构和算法。
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...
自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...