我的java笔记

来源:互联网 发布:数据的波动程度 编辑:程序博客网 时间:2024/04/30 05:50
********** 01 *********************************************************************** 
java: 为什么nio要比老IO效率高?(以下讨论在服务器端!):新io:有则处理,没有则不处理(当然在判断是否有时要一直循环:select); 旧IO:有也处理,没有也处理(当然在判断是否有时要一直循环:accept)。 
其实在nio中也需要多线程(如常用线程池)来进一步提高效率。 
在对服务器程序只有一个线程的情况下,nio要比老io快,这主要是因为:一一对应客户端的socket(服务器程序中)在从流中读时会忙等! 
新IO在获取连接时(select(timeout))时和老IO的效率几乎一样,只是select的方式可以更好的定义超时(不会抛出异常),而旧IO虽然也可定义超时,但会抛出异常,用这种抛出异常的方式去处理超时显得有些不优雅! 
在使用多线程时,新IO的作法是用主线程去轮询需要处理的信道,有则处理,处理时可用多线程进行具体处理过程从而提高效率。而旧IO虽然也用多线程去处理,但由于每个线程都会调用read方法,从而会造成忙等!而忙等也是在运行(不断的循环去检察输入流中是否会有信息可读),也要占用CPU及其它系统资源!!所以效率要低! 
当CPU有空闲时,使用多线程才可能提高效率,如果所有单个线程会100%占用CPU的话,那么分多线程进行处理,反而使服务器的率更低:因为多线程需要调度和切换,这需要时间。当然,多线程对客户端来说是一般友好的!相比服务器端用单线程去一个一个轮流处理客户端请求,多线程显然要让某个客户端更快的得到响应。 
处理消息开线程和接受客户端开线程又不同。传统的给客户端开的那些线程由于经常阻塞所以效率低。这里是要开线程处理消息,这个线程又不用等待,直接工作了,跟阻塞沾不上边的了。 
注意:阻塞与忙等在这里是同一概率,不要认为阻塞时程序没有在运行!!!只有线程挂起时才没有在运行(不占cpu),这时也有人叫它阻塞,但最好还是称其为挂起。 
从头到尾看一遍TCP/IP in java那本书中第5章的例子,超级经典! 
以下是网摘: 
while ((str = in.readLine()) != null) 
问题所在。。。 

有几个地方确实非常影响效率,在这里我想先提出来:  http://blog.163.com/z_hongc/blog/static/21364001201162512019169/ 
1、 连接侦听线程一直在侦听,有连接请求过来则会返回,没有则会阻塞;这样这个线程就会一直挂着;如果时时刻刻都有很多的连接过来,这个线程还会充分发挥它的作用,但其实大部分时候,连接请求并没有这么频繁,所以这个线程大部分时间是阻塞的;这样为了这样一个功能单独利用一个线程就有点浪费了。 
2、 分发线程不停的轮询过程是导致整个系统效率低下最严重的一块,分发线程不停的轮询连接对象队列,其实分发线程并不知道哪个线程需要发送数据,哪些线程需要接收数据,而他只是盲目地从队列的头遍历到队列的尾部,如果发现没有可操作的连接对象则休眠一段时间;其实在大部分情况下,连接对象并不是时时刻刻都有数据发送和接收,所以这个分发线程大部分时间空循环,白忙了;并且这个休眠时间也不好控制,如果时间长了,则程序的即时性不够,如果太短了,程序似乎就是在空跑了。 
3、 在连接对象上发送和接收数据包的时候,这些方法都是阻塞操作的;所以当有大量的数据可接收和发送的时候,这种阻塞的操作时非常浪费资源的。 
    以上所提出的问题,如果是在并发规模比较小的情况下,是没有什么问题;但确实有很大的改进空间。上面的问题归结起来主要是两个: 
1、 当有连接请求过来或者有 Socket 连接有数据可读可写的时候,我们不会立即知道,我们必须要一个一个的轮询,我们能否有一种机制,即是,当有连接请求过来或者连接有数据可读或者可写的时候,直接通知我们来处理,而不需要我们主动轮询。 
2、 当读数据或者写数据的时候,所有的方法都阻塞了,能不能有一种办法当我们写数据或者接收数据的时候不用阻塞,而是直接返回,这样就明显提高了线程的使用率了。 
    值得我们庆幸的是,在 Java 的 JDK1.4 之后的版本,提供了 NIO 包,这里提出了事件驱动的 I/O 编程模式和非阻塞信道的概念, NIO 里面的 Selector 对象解决了上面提出分发和轮询的问题, Channel 接口解决了阻塞读写的问题。我相信这些组件能够帮我们解决上面所提出的所有问题。所以下面有很大一部分篇幅来介绍 NIO 的使用和一些底层的机制。 
http://haoel.blog.51cto.com/313033/124582 
http://haoel.blog.51cto.com/313033/124578 Java NIO类库Selector机制解析 

********** 02 *********************************************************************** 
设计,重构,优化 
开发效率(进度),性能(质量),可读性,可扩展性。后两者属于可维护性范畴。 
为什么要重构: 
1. 保证质量,提高开发效率(从长远看):可维护性(可读性,可扩展性),发现bug,便于进行性能优化。 质量效率性能维护bug 欣赏成长 
2. 前辈(技术总监)的认可与欣赏 
2. 自己的成长 
为什不重构(一般人看来): 
1. 可有可无的额外工作:浪费时间和精力 
2. 可能引入新的bug从而破坏系统 

********** 03 *********************************************************************** 
设计模式:指在软件开发中,经过验证的,用于解决在特定环境下、重复出现的、特定问题的解决方案。 
24个设计模式:简 外适单工抽生原 中代观命迭组模 策状备享解装职 桥访 
简:选择实现。是对创建某个接口或抽象类的对象的方式方法的封装。 
外:封装效互,简化调用。减少接口(方法),是对子系统功能和接口的封装,便于客户端利用外观类定义的相对较少的方法去操纵多个子系统的子方法。 

********** 04 *********************************************************************** 
接口:外观窗口,封装隔离,面对需求 
接口:是行为的封装体,是系统与系统之间的隔离手段和相互影响和通信的交互窗口,一般本系统是整个系统环境的一个子系统,对其它子系统提供某种服务。 
接口是系统可插拨性的保证。 
接口是被其隔离部份的外观。 
典弄例子:MVC 
所谓组件,从设计上讲,组件就是能完成一定功能的封装体。 
一个具体类要实现(implements)一个接口必须全部实现所有的接口方法,但一个抽象类实现(implements)一个接口时不必要实现该接口的所有接口方法,甚至可以不实现任何接口方法。 

********** 06 *********************************************************************** 
java java se java基础: 
用类组部顺活状 
类图:http://www.cnblogs.com/riky/archive/2007/04/07/704298.html 
  关联(实:实箭,聚合成(空棱),组合包含(实棱)),泛化(实空三角),实现(虚空三角),依赖(虚箭) 
活动图:过程和控制(分支与并行) 

数据范围: 
数值形:256(-128 127) 65536(-32768 32767) 约42亿 约1844亿亿 
整数默认是int 浮点数默认是double 
浮点数还有三个值:正无穷,负无穷,非数 
float: 1符号 + 8指数 + 23尾数 
double: 1符号 + 11指数 + 52尾数 
字符型直接量有三种表示方法: 单个字符如‘1’,转义字符如‘\n’,十六进制unicode字符:‘\u0002’,0002是十六进制,有二个字节 
基本数据类型(具体共8种):数值型(整数,字符型,浮点数)和布尔型(boolean),四整一恰(char),二浮一布(boolean)  1248248 
特殊类型:(数)组时(间) 
集合结构:set,queue,list,map 
直接量只有以下三类有(具体只有8种): 
基本数据类型中除byte和short外的所有数据类型。 
字符串 
null类型的直接量:null(只这一个值) 
运算符:算赋比逻位类 算赋位扩比逻三类 
算:加减乘除余自加自减负 
赋 
位:与或非异或左右右 7 
扩:加减乘除余与或异或左右右 
比:大小等不等 
逻:与与或或非异或 
流程:顺分循 
  if,switch,while,do,for,foreach 

Arrays对数组进行操作:填(fill)序(sort)查(search)比(equals)移(copyOf)变(toString) 
数据库:添删改查移/变 
java的成份:类,接口,枚举,数组,初始化块(器),属性,构造器,方法,标注 
类中的成份:9种 
接口中的成份:7种 无初始化器,无构造器 方法全是公有抽象方法 属性全是公有静态常量 其它成份全是公有静态的 
枚举的成份:9种,其中构造器只能是private的,默认的就是,而且private关键可省略。 枚举类不能是final的,因为它要保证有子类存在,否则,枚举就失去了其存在的意义了。 
数组:类型有一个class属性,对象有一个length属性 
时间:date,canlender,timezone 
成份之间的关系:抽重  继多封 
接口与抽象类:从概念上,存在的目的和意义上来说:外观窗口,封装隔离。从语法表现上来说:其内部成份与类有不同。 
接口(外观窗口,封装隔离):接口是它所对应的系统的外观,是该系统与周围环境中的其它系统相互影响和通信的窗口。对外部系统而言,接口表示它所对应的系统能向外部系统提供的服务。对接口所对应的系统而言,它是本系统接收外部系统的消息的窗口。接口的作用:封装和隔离。 
final常量(静态和非静态): 在整个初始化过程中只能而且必须被显示赋值或初始化一次。实际上存在二次的初始化(成员列表中声明时一次(如果声明时即显示赋值,则在该次初始化时即会设该被赋的值为默认值,之后的初始化器不能再赋值了),初始化器和构造器初始化过程中赋值中最多一次)。写常量时,只能被显式地写一次!读常量时,必须保证引用语句在声明语句之后,而且引用之前必须已被显示的赋了值! 
注: 
  1. 不允许在对象级成员变量的初始化过程中创建该类的对象实例!!即在类T中,整个初始化过程中不允许有以下语句或类似语句:T t = new T(...); //其中t为非静态变量 
  2. 若静态final变量在声明时即被赋了初值,则这个变量在编译时即已确定了值(该量又被叫作编译时常量),所以可以在其所在类没有被加载之前即可引用它!!因为:程序中所有使用到编译时常量的地方,在编译时即被直接替换成该常量的值。也即实际上没有真正使用到那个静态final变量,所以不会去加载其所在的类。 
手机以人为本,是人的延伸,助人目的: 
人与环境的交互手段:视听嗅味触思(意:寻求思所依赖的体系和规则,即为法)感(幸福,快乐:静与动(安全感,快感(物理,精神))) 
六欲:色、声、香、味、触、法 ;七情:喜、怒、哀、惧、爱、恶、欲 。 
   佛家的六根:眼、耳、鼻、舌、身、意 
  佛家的六尘:色、声、香、味、触、法 
  儒家的七情:喜、怒、哀、惧、爱、恶、欲 
  医家的七情:喜、怒、忧、思、悲、恐、惊 
所有有用的东西我们都可以想办法将其用语言进行描述。这个语言本身就是信息。 
手机的本质:有助于文图音视等信息的交互。 
枚举自成体系,它包括自己和自己的子类对象,所以没有去继承其它类的能力,只能实现某些接口:Syntax error on token "extends", implements expected 
正规表达式:用数轴思维模型找内在线索和思路。本质是:匹配字符串的模板。 
   匹配单个普通字符: 
      从类型上单个匹配:点的丝娃 . d D s S w W 
      从范围中查找匹配:方括号(与或非) 
   匹配单个功能字符:转义 
   匹配次数:?*+ 
   匹配边界: 
      整个字符串的边界:^ $ 
      串的子单元(单词)的边界: \b \B \A \G \Z \z 
   子表达式(嵌套): 
      次数:{} 
   三种模式:贪(无,默认)免(?)占(+) 
     

数据库mysql: 
查cmd:1234  DCL(revoke) DML(insert,delete,update) DDL(create,alter,drop,truncate) 
表数约视 索函存触 
约:外主唯空 
三大数据类型:数值型,字符型,时间 
where条件子句:比逻:大小等不等 between,like,in,is null; not and or.  like后面不是常规的正规表达式!用‘_’表示单个任意字符,用“%”表示零个或多个任意字符。可用“\”转义“_”和“%”成其本身. 
异常: 
finally:保证在离开try和catch(如果有机会被执行到的话)结构结束时finally里面的语句被执行一次(而且一定是离开前最后才执行finally语句块中的语句)。 
JVM与反射: 
虚拟机圈子:http://hllvm.group.iteye.com 
莫枢的博客:http://rednaxelafx.iteye.com 
周志明:   http://icyfenx.iteye.com/blog/1119214 
加载,连接(验证,准备(即注册所有成员然后赋一个默认值,如果是静态常量且声明时有了初值,则这个初值即作为其默认值,之后的初始化过程不会再有赋值的可能),解析),初始化 
根扩系用U 
扩:sun.misc.Launcher$AppClassLoader 
系:sun.misc.Launcher$ExtClassLoader 
扩系用U都是ClassLoader.java的子类 
扩的父加载器是根加载器,但扩.getParent是返回null的。 
扩是系的父回载器,可用系.getParent方法返回扩的实例。 
系是用户自定的classloader的父加载器。 
java.net.URLClassLoader.java是classloader.java的一个实现类,它的父类加载器是系。 
big左高:多字节在内存中的存放方法(big-endian和little-endian) 
String类型(和八种基本类型的封装类)的变量并不一定会指向一个堆内存中的对象!如String a = "abc"; 中的abc是保存在栈中的数据区里的,所以a指向栈中的数据对象! 
内存:常量区(该区域在程序运行过程中只读),静态区(类信息:静态成员),动态区(方法或线程栈区(以称为帧(即一个方法单元)的基本单元压栈和出栈,包括:指令区和数据区),堆区(存放用new关键字所创建的对象)) 
其它存储器:硬盘等(持久化对象) 
每个java应用(进程)对应一个JVM实例,每个JVM实例对应一个静态区,一个栈,一个堆。 
类(包括数组)都有一个特殊的属性量:class属性,它指向该类的Class对象。但这个class属性不能通过类的实例对象进行访问,如需访问得到该Class对象的引用,需调用实例对象的getClass方法。 
示例: 
类:Class c= Object.class; // ok! 
数组: Class c=int[].class; // ok! 
枚举:Class c= E.class; // E为任意一个枚举类 ok! 
接口:Class c= I.class; // I为任意一个接口 ok!