1. java中重载和重写有什么区别?分别用什么关键字?
首先说重载:
(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。 重载Overloading是一个类中多态性的一种表现。
(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。 调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。但无法以返回型别作为重载函数的区分标准。
其次说重写:
(1)父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中, 子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。
方法重写又称方法覆盖。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
(3)子类重写的方法访问权限不能低于被重写的父类相应的方法。
重载的规则:
1、必须具有不同的参数列表,返回类型不能作为判断依据;
2、可以无返回类型,只要参数列表不同就可以了;
3、可以有不同的访问修饰符;
4、可以抛出不同的异常;
重写的规则:
1、参数列表和返回类型必须完全与被重写的方法相同,否则不能称其为重写而是重载。
2、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
3、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如: 父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。
重载与重写的区别:
重载可以在同一类中,也可以在父子类中。
重写仅在于子类覆写父类,且访问权限不能比父类访问权限低。
2. java线程如何启动?
1.继承Thread类创建线程
2.实现Runnable接口创建线程
3.使用Callable和Future创建线程
public class ThirdThread implements Callable<Integer> {
public Integer call() {
int i = 0;
for (; i < 60; i++) {
System.out.println(Thread.currentThread().getName() + "循环变量i的值是 : " + i);
}
return i;
}
public static void main(String[] args) {
ThirdThread rt = new ThirdThread(); // 创建Callable对象
FutureTask<Integer> task = new FutureTask<Integer>(rt);// 使用FutrueTask来包装Callable对象
for (int i = 0; i < 60; i++) {
System.out.println(Thread.currentThread().getName() + "-------" + i);
if (i == 10) {
new Thread(task, "有返回值的线程").start(); // 实际上还是以Callable对象创建并启动线程
}
}
try {
System.out.println("子线程的返回值 :" + task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. java中加锁的方式有哪些,怎么个写法?
采用java加锁方式来同步 synchronized
采用数据库来加锁:select value from t_table_id where table_name=? for update
4. 乐观锁和悲观锁解释一下
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。
多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。
典型的冲突有:
l 丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。
l 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。
为了解决这些并发带来的问题。 我们需要引入并发控制机制。
乐观锁应用
1. 使用自增长的整数表示数据版本号。更新时检查版本号是否一致,比如数据库中数据版本为N,更新提交时version=N+1,使用该version值(=7)与数据库version+1(=7)
作比较,如果相等,则可以更新,如果不等则有可能其他程序已更新该记录,所以返回错误。
2. 使用时间戳来实现.
注:对于以上两种方式,Hibernate自带实现方式:在使用乐观锁的字段前加annotation: @Version, Hibernate在更新时自动校验该字段。
悲观锁应用需要使用数据库的锁机制,比如SQL SERVER 的TABLOCKX(排它表锁) 此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。
这将防止其他进程读取或修改表中的数据。
5. ORACLE中的SQL如何进行优化,都有哪些方式?
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们. 首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表), 最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.
3. WHERE子句中的连接顺序.
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
4. SELECT子句中避免使用 ‘ * ‘
5. 减少访问数据库的次数
6. 使用DECODE函数来减少处理时间 使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
7. 用TRUNCATE替代DELETE
8. 用Where子句替换HAVING子句
9. 减少对表的查询 在含有子查询的SQL语句中,要特别注意减少对表的查询.
10. 通过内部函数提高SQL效率.
11. 使用表的别名(Alias) 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,
就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
12. 用EXISTS替代IN 在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.
14. 用表连接替换EXISTS
15. 用EXISTS替换DISTINCT
16. 基础表的选择
17. 多个平等的索引
18. 等式比较和范围比较
19. 不明确的索引等级 当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的.
20. 强制索引失效 如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少) .
21. 避免在索引列上使用计算. WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
22. 自动选择索引 如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性. 在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.
23. 避免在索引列上使用NOT 通常, 我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的 影响. 当ORACLE”遇到”NOT ,!=,
他就会停止使用索引转而执行全表扫描.
6. java中类的加载机制说一下
java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:
•Bootstrap ClassLoader 负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
•Extension ClassLoader 负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
•App ClassLoader 负责加载当前java应用的classpath中的所有类。
其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系如下:
Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。
但是这并不是继承关系,只是语义上的定义,基本上,每一个ClassLoader实现,都有一个Parent ClassLoader。
可以通过ClassLoader的getParent方法得到当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,
因为它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。
由于classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这
个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入。
所以,当我们自定义的classloader加载成功了com.company.MyClass以后,MyClass里所有依赖的class都由这个classLoader来加载完成。
7. 介绍一下自己最近做的一个典型的项目
做的金融票据理财产品,包括即将上线的一些类似产品,在用户高并发访问的情况下,如何做到库存有效扣减,避免未锁定库存时导致数据库数据不一致。 进行了模板类单步控制执行,数据库进行了可重复读控制
a、 可重复读(Repeatable Read,RR)
b、读稳定性(Read Stability,RS)
c、游标稳定性(Cursor Stability,CS)
d、未提交读(Uncommitted Read,UR)
1、可重复读(RR -- Repeatable Read)
a、可重复读隔离级别是最严格的隔离级别。在使用它时,一个事务的影响完全与其他并发事务隔离:脏读、不可重复读、幻像读都不会发生。
当使用可重复读隔离级别时,在事务执行期间共享(S)锁定该事务以任何方式引用的所有行。因此,如果在同一个事务中发出同一个SELECT语
句两次或更多次,那么产生的结果数据集总是相同的。因此,使用可重复读隔离级别的事务可以多次检索同一行集,并可以对它们执行任意操作,
直到由提交或回滚操作终止事务。但是,在事务存在期间,不允许其他事务执行会影响该事务正在访问的任何行的插入、更新或删除操作。为了确保这种行为,
锁定该事务所引用的每一行 -- 而不是仅锁定被实际检索或修改的那些行。因此,如果一个表中有1000行,但只检索两行,则整个表(1000行,而不仅是被检索的两行)
都会被锁定。
b、如果使用可重复读隔离级别,不管从表中读多少数据,整个表上都加S锁,直到该事务被提交或回滚,表上的锁才会被释放。
这样可以保证在一个事务中即使多次读取同一行,得到的值也不会改变。另外,在同一个事务中如果以同样的搜索标准重新打开已被处理过的游标,
那么得到的结果集不会改变。可重复读相对于读稳定性而言,加锁的范围更大。对于读稳定性,应用程序只对符合要求的所有行加锁,而对于可重复读,
应用程序将对整个表都加S锁。
c、可重复读(RR),不可能出现丢失更新、脏读和幻像读的情况;
2、读稳定性(RS -- Read Stability)
a、读稳定性隔离级别没有可重复读隔离级别那么严格。读稳定性(RS)可以防止脏读和不可重复读,但可能出现幻像读。在使用这个隔离级别时,
只锁定事务实际检索和修改的行。因此,如果一个表有1000行,但只检索两行(通过索引扫描),则只有被检索的两行(而不是所扫描的1000行)
被锁定。因此,如果在同一个事务中发出同一个select语句多次,那么每次产生的结果集可能不同。
b、与可重复读隔离级别一样,在读稳定性隔离级别下运行的事务可以检索一个行集,并可以对它们执行任意操作,直到事务终止。
在这个事务存在期间,其他事务不能执行那些会影响这个事务检索到的行集的更新或删除操作(其他事务可以更新或删除 不影响该事务检索到的行集的数据);
但是其他事务可以执行插入操作。如果插入的行与第一个事务的查询的选择条件匹配,那么这些行可能作为幻像出现在后续产生的结果数据集中。
其他事务对其他行所作的更改,在提交之前是不可见的。
c、如果使用读稳定性(RS)这种隔离,在一个事务中将有N+1个锁,其中N是所有被读取(通过索引扫描)过的行的数目,这些行上都会被加上NS锁,
在表上加1个IS锁。这些锁直到事务被提交或回滚,才会被释放。这样可以保证在一个事务中即使多次读取同一行,得到的值不不会改变。但是,使用读稳定性,
在一个事务中,如果使用同样的搜索标准重新打开已被处理过的游标,那么结果集可能改变(可能会增加某些行,这些行被称为幻影行-Phantom)。
这是因为RS不能阻止通过插入或更新操作在结果集中加入新行。
d、读稳定性(RS),只锁定应用程序在工作单元中检索的那些行。它确保在某个工作单元完成之前,在该工作单元运行期间的任何限定行读取不被其他应用程序进程更改,
且确保不会读取由另一个应用程序所更改的任何行,直到该进程提交了这些更改。读稳定性,不可能出现“不可重复读”情形。
e、“读稳定性”,其中一个目标是提供较高的并行性程度以及数据的稳定视图。为了有助于达到此目的,优化器确保在发生锁定升级前不获取表级锁定。
f、“读稳定性”隔离级别最适用于包括下列所有特征的应用程序:
在并发环境下运行;需要限定某些行在工作单元运行期间保持稳定;在工作单元中不会多次发出相同的查询,或者在同一个工作单元中发出多次查询时,
并不要求该查询获得相同的回答。
3、游标稳定性(CS -- Cursor Stability)
a、游标稳定性隔离级别,可以防止脏读,但有可能出现不可重复读和幻像读。游标稳定性只锁定事务声明并打开游标当前引用的行。
b、当使用游标稳定性隔离级别时,事务通过游标从表中检索行时,其他事务不能更新或删除游标所引用的行。但是,如果被锁定的行本身不是用索引访问的,
那么其他事务可以将新的行添加到表中,以及对被游标锁定行前后的行进行更新和删除操作。所获取的锁一直有效,直到游标重定位或事务终止为止
(如果游标重定位,原来行上的锁就被释放,并获得游标现在引用的行上的锁)。此外,如果事务修改了它检索到的任何行,那么在事务终止之前,
其他事务不能更新或删除改行,即使游标不再位于被修改的行。例如:一个表中有1000行数据,我们只检索其中的两行数据,那么对于可重复读(RR)
隔离级别会锁住整个表;读稳定性(RS)会对读到的数据(两行)加锁;游标稳定性(CS)隔离级别只对游标当前所在的那一行加锁,游标所在行的前一行和下一行都不加锁。
c、结果集中只有正在被读取的那一行(游标指向的行)将被加上NS锁,在表上加IS锁。其他未被处理的行上不被加锁。CS只能保证正在被处理的行的值不
会被其他并发的程序所改变。
d、当在行上定位游标时,游标稳定性CS会锁定任何由应用程序的事务所访问的行。此锁定在读取下一行或终止事务之前有效。但是,如果更改了某一行上的任何数据,
那么在对数据库提交更改之前必须挂起该锁定。
e、对于具有“游标稳定性”的应用程序已检索的行,当该行上有任何可更新的游标时,任何其他应用程序都不能更新或删除该行。“游标稳定性”应用程
序不能查看其他应用程序的未提交更改。
f、与可重复读(RR)和读稳定性(RS)隔离级别一样,其他事务在其他行上进行的更改,在这些更改提交之前对使用游标稳定性(CS)
隔离级别的事务(这时默认的隔离级别)来说是不可见的。
g、游标稳定性,可能会出现不可重复读和幻像读现象。
4、未提交读(UR - Uncommitted Read)
a、未提交读隔离级别是最不严格的隔离级别。实际上,在使用这个隔离级别时,仅当另一个事务试图删除或更改被检索的行所在表时,
才会锁定这个事务检索的行。因为在使用这种隔离级别时,行通常保持未锁定状态,使用脏读、不可重复读和幻像读都可能会发生。因此,
未提交读通常用于访问只读表和视图的事务,以及某些执行select语句的事务。
b、未提交读UR,运行应用程序读取其他事务未落实的更改。但是对于只读和可更新两种不同的游标类型而言,UR的工作方式有所不同。
对于可更新的游标,当它使用隔离级别UR运行程序时,应用程序会自动使用隔离级别CS。
c、使用UR,对于只读操作,不加行锁。典型的只读操作包括:SELECT语句的结果集只读(比如语句中包括ORDER BY子句);
定义游标时指明FOR FETCH ONLY或FOR READ ONLY。
d、UR,最大程度上允许并发;若需读取未提交的数据,该隔离级别是唯一选择。
e、只读游标可访问大多数其他事务的未提交的更改。但是,当该事务正在处理时,不能使用正由其他事务创建或删除的表、视图和索引。
其他事务的任何其他更改在提交或回滚前都可被读取。
DB2默认的隔离级别为:游标稳定性(CS)
8. 在项目中遇到了哪些问题,自己是如何解决的
项目涉及的周边系统比较多,这个时候就需要按照优先级先进行分类,并将自己需要等待解决的问题一一罗列出来,然后逐个按照紧急程度逐个找接口人解决。
9. 说一下有哪些常用的设计模式
1、 工厂模式:
客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工
厂类也要做相应的修改。如:如何创建及如何向客户端提供。
2、建造模式:
将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。
建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
3、工厂方法模式:
核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现
的接口,而不接触哪一个产品类应当被实例化这种细节。
4、原始模型模式:
通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动
态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
5、单例模式:
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
6、适配器(变压器)模式:
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
7、桥梁模式:
将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化
之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
8、合成模式:
合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的
关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。
9、装饰模式:
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些
功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
10、门面模式:
外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只
有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。
11、享元模式:
FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状
态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相
互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,
而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
12、代理模式:
代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构
采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象
与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象
必须有系统的其他角色代为创建并传入。
13、责任链模式:
在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处
理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:
承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。
14、命令模式:
命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式
允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被
执行以及是怎么被执行的。系统支持命令的撤消。
15、解释器模式:
给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中
的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的
任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对
象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。
16、迭代子模式:
迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够
包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象
都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
17、调停者模式:
调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用
发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。
调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
18、备忘录模式:
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,
并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
19、观察者模式:
观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知
所有观察者对象,使他们能够自动更新自己。
20、状态模式:
状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,
每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
21、策略模式:
策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影
响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开
来,算法的增减,修改都不会影响到环境和客户端。
22、模板方法模式:
模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。
不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
23、访问者模式:
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。
访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问
者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者 模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类
中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不
同的等级结构的成员类。
10. 事务有哪些特性,在ORACLE中隔离有哪些级别
一.什么是事务
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,
一个事务中的一系列的操作要么全部成功,要么一个都不做。
事务的结束有两种,当事务中的所以步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消撤消之前到事务开始时的所以操作。
二.事务的 ACID
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。
如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,
这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
1、脏读取(dirty read):一个事务读取了被其他事务写入但还未提交的数据。
2、不可重复读取(nonrepeatable read):一个事务再次读取其之前曾经读取过的数据时,发现数据已被其他已提交的事务修改或删除。
3、不存在读取(phantom read):事务按照之前的条件重新查询时,返回的结果集中包含其他已提交事务插入的满足条件的新数据。
ANSI/ISO SQL 标准(SQL92)定义了四种事务隔离级别(transaction isolation level)
现象隔离级别 脏读取 不可重复读取 不存在读取
未提交读取(read uncommitted) 允许 允许 允许
已提交读取(read committed) 不允许 允许 允许
可重复读取(repeatable read) 不允许 不允许 允许
串行化(rerializable) 不允许 不允许 不允许
Oracle 支持三种事务隔离级别:已提交读取,串行化,以及 SQL92 中没有包含的只读模式(read-only mode)。
已提交读取是 Oracle 默认使用的事务隔离级别。
Oracle 支持以下三种事务隔离级别(transaction isolation level)。
隔离级别 描述
已提交读取 Oracle 默认使用的事务隔离级别。事务内执行的查询只能看到查询执行前(而非事务开始前)就已经提交的数据。
Oracle 的查询永远不会读取脏数据(未提交的数据)。Oracle 不会阻止一个事务修改另一事务中的查询正在访问的数据,
因此在一个事务内的两个查询的执行间歇期间,数据有可能被其他事务修改。举例来说,如果一个事务内同一查询执行两次,
可能会遇到不可重复读取或不存在读取的现象。
串行化 串行化隔离的事务只能看到事务执行前就已经提交的数据,以及事务内 INSERT , UPDATE ,及 DELETE 语句对数据的修改。
串行化隔离的事务不会出现不可重复读取或不存在读取的现象。
只读模式 只读事务只能看到事务执行前就已经提交的数据,且事务中不能执行 INSERT , UPDATE ,及 DELETE 语句。
已提交读模式:SET TRANSACTION ISOLATION LEVEL=READ COMMITTED;
串行模式:SET TRANSACTION ISOLATION LEVEL= SERIALIZABLE;
只读模式:SET TRANSACTION= READ ONLY;
(经笔者实验以上命令在非sysdba用户下可以成功执行,sysdba下不能执行,待验证正确性)
如果在每个事务开始时都使用 SET TRANSACTION 语句,将加重网络及处理器的负担。用户可以使用 ALTER SESSION 语句 改变一个会话所有内事务的默认隔离级别:
1、ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
2、ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
11. 使用memcached是一个什么样的原理
Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。
同时,memcached用的是一个二级散列,通过一张大hash表来维护。Memcached有两个核心组件组成:服务器端(server)和客户端(client),
在一个memcached的查询中,client先通过计算key的hash值来确定kv对所处在的server位置。当server确定后,客户端就会发送一个查询请求给对应的server,
让它来查找确切的数据。因为这之间没有交互以及多播协议,所以memcached交互带给网络的影响是最小化的。
12. Memcached的内存管理机制
memcached会预先分配内存,首先,这里有3个概念:
1. slab
2. page
3 . chunk
解释一下,一般来说一个memcahced进程会预先将自己划分为若干个slab,每个slab下又有若干个page,每个page下又有多个chunk,
如果我们把这3个咚咚看作是object得话,这是两个一对多得关系。再一般来说,slab得数量是有限得,几个,十几个,或者几十个,
这个跟进程配置得内存有关。而每个slab下得page默认情况是1m,也就是说如果一个slab占用100m得内存得话,那么默认情况下这个slab
所拥有得page得个数就是100,而chunk就是我们得数据存放得最终地方。
Chunk用于缓存记录的内存空间。
Slab Class :特定大小的chunk的组。
Memcached的内存分配以page为单位,默认情况下一个page是1M ,可以通过-I参数在启动时指定。如果需要申请内存 时,memcached会划分出一个
新的page并分配给需要的slab区域。Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责
一定范围内的数据存储,其大小可以通过启动参数设置增长因子,默认为1.25,即下一个slab的大小是上一个的1.25倍。如 下图,每个slab只存储
大于其上一个slab的size并小于或者等于自己最大size的数据。如下图所示,需要存储一个100Bytes的对象时,会选用112Bytes的Slab Classes
六.Memcached的缓存策略
当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端
由app设置并作为参数传给ms的。
同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。
七.Memcached的客户端
Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等。其中面向Java的三种Memcached客户端包括memcached client for java、
spymemcached和xmemcached 。
13. 如何存放数据到memcached集群中
14. 一致性哈希算法的实现原理。
15. JVM中堆是如何管理的,JVM的内存回收机制
堆内存是内存中最重要的一块,因为Java性能的优化,主要就是针对这部分内存的。所有的对象实例及数组都是在堆上面分配的
判断哪些对象可回收:
GC是通过对象是否存活来决定是否进行回收,判断对象是否存活主要有两种算法:引用计数算法、可达性分析算法
•引用计数算法
引用计数的算法原理是给对象添加一个引用计数器,每被引用一次计数器加1,引用失效时减1,当计数器0后表示对象不在被引用,可以被回收了,引用计数法简单高效,但是存在对象之间循环引用问题,可能导致无法被GC回收,需要花很大精力去解决循环引用问题
•可达性分析算法
可达性分析的算法原理是从对象根引用(堆栈、方法表的静态引用和常量引用区、本地方法栈)开始遍历搜索所有可到达对象,形成一个引用链,遍历的同时标记出可达对象和不可达对象,不可达对象表示没有任何引用存在,可以被GC回收
如何回收:
找到可回收对象后,如何进行回收呢?
内存回收算法主要有标记-清除、停止-复制、标记-整理,不同算法使用不同的场景,总体来说停止-复制算法适合对象存活时间短,存活率低的新生代,标记-清楚和标记-整理算法适合对象存活时间长,存活率高的老年底
•标记-清除(Mark-Sweep)
通过可达性分析算法标记所有不可达对象,然后清理不可达对象。这种算法会形成大量的内存碎片
•停止-复制(Stop-Copy)
将新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复,当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代(这时我们可能回想,若是老年代也满了咋办,若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收,若是内存还不够呢。。。,还不够那不废话了吗,OutOfMemory,不陌生吧哈哈)。从停止-复制算法的原理上我们可以看到,这种算法对于存活率较低的对象回收有着非常高的效率,而且不会形成内存碎片,但是会浪费一定的内存空间,适合对象存活率较低的新生代使用,如果在对象存活率较高的老年代采用这种算法,那将会是一场灾难
•标记-整理(Mark-Compact)
通过可达性分析算法标记所有不可达对象,然后将存活对象都向一个方向移动,然后清理掉边界外的内存。这种算法是将存活对象向着一个方向聚集,然后将剩余区域清空,这种算法适合对象存活率较高的老年代
GC回收机制:分代收集算法:
JVM内存收集算法基本上都是采用分代收集算法,即将内存划分为新生代、老年代,也有人把方法区算做永久代
•新生代
对象被创建时,内存分配都是发生在新生代(大对象直接分配在老年代),绝大多数对象都是朝生夕灭,创建后很快就会不在使用,变为不可达的对象,被GC回收掉。新生代的对象存活率很低(到底有多低?研究表明有高达98%的对象创建后很快就消亡,想象一下平时编程,除了全局变量,局部变量在退出调用方法后还有几个能存活),存活时间都很短,新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)
•老年代
当对象在新生代发生了多次Minor GC后仍然存活的对象即进入老年代,老年代的对象比新生多很多,当然了内存比新生代也大很多(大概比例是1:2,即新生代占用堆内存总量的1/3),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高
一般来说我们所说的GC都是发生在新生代和老年代,新生代对象存活时间短,存活率低一般采用停止-复制算法,老年代对象存活时间长,存活率高,一般采用标记-整理、标记-清楚算法,具体采用何种算法和具体采用的垃圾收集器有关
GC里面有些类似未成年人和成年人,新创建的对象为新生代,新生代想要成为老年代需要经过一定的成长(总得一点点长大是吧),新创建的对象年龄为1,每发生一次Minor GC,存活对象的年龄增加1,当经历了15次Minor GC后,仍然存活的对象达到15岁,成达到法定成年年龄15岁(默认是15),正式成为成年人(老年代),对象成年后也就没有了年龄概念,直到对象死亡,会一直呆在老年代,当然也有一些老不死的(静态变量、常量等),会与世长存,除非地球灭亡(GC崩溃)
GC收集器:
GC采用分代回收算好后,起着重要作用的是GC收集器,GC收集器分为新生代收集器和老年代收集器,不同的收集器使用不同的收集算法,有着不同的特点,由于目前的收集器在内存回收时无法消除(Stop-the-world),即在回收内存时不可避免的停止用户线程,目前的收集器只能使停顿时间越来越短,但是无法彻底消除,主要的收集其中Parallel Scavenge和Parallel Old是追求吞吐量为目标,其它的收集器都是追求高响应,低停顿,
新生代收集器:Serial、PraNew、Parallel Scavenge
老年代收集器:Serial Old、Parallel Old、CMS
•Serial收集器(复制算法)
新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
•Serial Old收集器(标记-整理算法)
老年代单线程收集器,Serial收集器的老年代版本。
•ParNew收集器(停止-复制算法)
新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
•Parallel Scavenge收集器(停止-复制算法)
并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。
•Parallel Old收集器(停止-复制算法)
Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先
•CMS(Concurrent Mark Sweep)收集器(标记-清理算法)
高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择
•G1(Garbage-First)收集器(标记-整理算法、停止复制算法)
GC最新型号,高富帅,高并发、可预测停顿、分代收集,不出意外未来主流将会逐步替代CMS,g1模糊了分代概念,虽然还是分为新生代和老年代,但是新生代和老年代不再是物理隔离,而是将内存分为n个region,以region为清理单位,整体采用标记-整理算法,region内部使用停止-复制算法。
16. spring的aop的实现方法
17. 分布式消息队列,分布式缓存
18. rpc方面
19. hashmap源码实现
20. Java异常的续承层次结构,讲述异常的续承关系
21. https握手过程
1、客户端浏览器给服务器发送自己支持的对称、非对称加密算法和摘要函数列表以及一个随机数。
2、服务器收到客户端的请求后选择特定的加密算法和摘要函数以及生成一个随机数,外加自己的证书发送给客户端。
3、客户端收到后先验证证书,如果证书受信就继续,否则终止。客户端从证书中获取到服务器的加密公匙,然后浏览器产生一个随机字符串作为pre-master-securet然后用服务器的公匙加密后发给服务器,告诉服务器说在后续的对称加密过程中会使用这个密匙。
4、服务器收到后用自己的私匙解密得到pre-master-securet,然后用一定的加密算法生成一个master-securet,然后加密后发给客户端,告诉客户端以后对称加密使用这个密匙。
22. java数据库问题定位和性能调优
23. 怎么量化分析链接池里的链接数配置事物
24. 如何量化分析还是要看上线后在线用户数
a、品牌
品牌包括在网站中所有审美的、设计相关的项目。它带给网站想要的组织形象或信息的创意。用于测量品牌的描述包括:
网站提供给访客有吸引力的和难忘的体验
网站的视觉效果与品牌特征保持一致
图像、附加内容和多媒体对于体验的增值
网站传达出品牌的感知预示
网站利用了媒体的能力来增强和扩展品牌
b、功能
功能包括所有技术方面的和“后台的”进程和应用。它让网站提供给所有最终用户交互式的服务,而且重要的是,注意这有的时候同时意味着前台公众用户和后台管理员。网站功能的描述包括:
用户及时获得对他们查询和提交信息的响应
任务进程的清晰告知(比如,成功页面或邮件更新提示)
网站和应用严格遵守通用的安全和隐私标准
在线功能与离线业务流程结合
网站包含管理员工具来加强管理员的效率
c、可用性
可用性带来的是所有网站元素和特性的总体易用性。可用性之下的二级主题包括导航和易用性(友好度)(注释:易用性处理的是使在线内容可用于用户的体验,享受和使用的问题)。可用性的描述包括:
网站防止错误发生,并帮用户从错误中恢复
整体网页侧重针对主要受众优化
网站帮助访问者达成一般目标和任务
网站遵循它自己的一致性和标准
网站为残疾用户提供内容
d、内容
内容指的是网站的实际内容(文本,多媒体,图像)及其结构,或信息架构。我们来看信息和内容是如何按照定义的用户需要和客户的商业需求组织的。测量内容的描述包括:
链接密度有足够的清晰度,且容易导航
内容组织方便用户达到目标
内容及时准确
内容适合客户需要和商业需求
多语言的综合性内容
在多数情况下,我会为这四种元素分别使用10到20个独立的描述。我建议你使用如上描述作为你创建你自己的分析的基础。请记住,如果你添加了更多的描述,你必须也调整20分的尺度,以便每个元素的总分为100。例如,如果你为每个元素使用10个描述,那么你的评分尺度应该是1-20。如果你为每个元素使用20个描述,你的尺度应该是1-5。
25. CORE文件详细怎么分析
在Unix系统下,应用程序崩溃,一般会产生core文件,可以根据core文件查找问题的所在,并做相应的分析和调试,是非常重要的。
就可以利用命令gdb进行查找,参数一是应用程序的名称,参数二是core文件,运行gdb
Core的意思是内存, Dump的意思是扔出来, 堆出来.
开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.
如何使用core文件?
gdb -c core文件路径 [应用程序的路径]
进去后输入where回车, 就可以显示程序在哪一行当掉的, 在哪个函数中.
为什么没有core文件生成呢?
有时候程序down了, 但是core文件却没有生成. core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便成生成core文件.
ulimit -c unlimited
core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号
26. JVM的堆是怎么规划的
http://blog.csdn.net/lifuxiangcaohui/article/details/37992725
首先说重载:
(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。 重载Overloading是一个类中多态性的一种表现。
(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。 调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。但无法以返回型别作为重载函数的区分标准。
其次说重写:
(1)父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中, 子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。
方法重写又称方法覆盖。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
(3)子类重写的方法访问权限不能低于被重写的父类相应的方法。
重载的规则:
1、必须具有不同的参数列表,返回类型不能作为判断依据;
2、可以无返回类型,只要参数列表不同就可以了;
3、可以有不同的访问修饰符;
4、可以抛出不同的异常;
重写的规则:
1、参数列表和返回类型必须完全与被重写的方法相同,否则不能称其为重写而是重载。
2、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
3、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如: 父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。
重载与重写的区别:
重载可以在同一类中,也可以在父子类中。
重写仅在于子类覆写父类,且访问权限不能比父类访问权限低。
2. java线程如何启动?
1.继承Thread类创建线程
2.实现Runnable接口创建线程
3.使用Callable和Future创建线程
public class ThirdThread implements Callable<Integer> {
public Integer call() {
int i = 0;
for (; i < 60; i++) {
System.out.println(Thread.currentThread().getName() + "循环变量i的值是 : " + i);
}
return i;
}
public static void main(String[] args) {
ThirdThread rt = new ThirdThread(); // 创建Callable对象
FutureTask<Integer> task = new FutureTask<Integer>(rt);// 使用FutrueTask来包装Callable对象
for (int i = 0; i < 60; i++) {
System.out.println(Thread.currentThread().getName() + "-------" + i);
if (i == 10) {
new Thread(task, "有返回值的线程").start(); // 实际上还是以Callable对象创建并启动线程
}
}
try {
System.out.println("子线程的返回值 :" + task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. java中加锁的方式有哪些,怎么个写法?
采用java加锁方式来同步 synchronized
采用数据库来加锁:select value from t_table_id where table_name=? for update
4. 乐观锁和悲观锁解释一下
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。
多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。
典型的冲突有:
l 丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。
l 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。
为了解决这些并发带来的问题。 我们需要引入并发控制机制。
乐观锁应用
1. 使用自增长的整数表示数据版本号。更新时检查版本号是否一致,比如数据库中数据版本为N,更新提交时version=N+1,使用该version值(=7)与数据库version+1(=7)
作比较,如果相等,则可以更新,如果不等则有可能其他程序已更新该记录,所以返回错误。
2. 使用时间戳来实现.
注:对于以上两种方式,Hibernate自带实现方式:在使用乐观锁的字段前加annotation: @Version, Hibernate在更新时自动校验该字段。
悲观锁应用需要使用数据库的锁机制,比如SQL SERVER 的TABLOCKX(排它表锁) 此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。
这将防止其他进程读取或修改表中的数据。
5. ORACLE中的SQL如何进行优化,都有哪些方式?
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们. 首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表), 最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.
3. WHERE子句中的连接顺序.
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
4. SELECT子句中避免使用 ‘ * ‘
5. 减少访问数据库的次数
6. 使用DECODE函数来减少处理时间 使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
7. 用TRUNCATE替代DELETE
8. 用Where子句替换HAVING子句
9. 减少对表的查询 在含有子查询的SQL语句中,要特别注意减少对表的查询.
10. 通过内部函数提高SQL效率.
11. 使用表的别名(Alias) 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,
就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
12. 用EXISTS替代IN 在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.
14. 用表连接替换EXISTS
15. 用EXISTS替换DISTINCT
16. 基础表的选择
17. 多个平等的索引
18. 等式比较和范围比较
19. 不明确的索引等级 当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的.
20. 强制索引失效 如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少) .
21. 避免在索引列上使用计算. WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
22. 自动选择索引 如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性. 在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.
23. 避免在索引列上使用NOT 通常, 我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的 影响. 当ORACLE”遇到”NOT ,!=,
他就会停止使用索引转而执行全表扫描.
6. java中类的加载机制说一下
java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:
•Bootstrap ClassLoader 负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
•Extension ClassLoader 负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
•App ClassLoader 负责加载当前java应用的classpath中的所有类。
其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系如下:
Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。
但是这并不是继承关系,只是语义上的定义,基本上,每一个ClassLoader实现,都有一个Parent ClassLoader。
可以通过ClassLoader的getParent方法得到当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,
因为它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。
由于classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这
个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入。
所以,当我们自定义的classloader加载成功了com.company.MyClass以后,MyClass里所有依赖的class都由这个classLoader来加载完成。
7. 介绍一下自己最近做的一个典型的项目
做的金融票据理财产品,包括即将上线的一些类似产品,在用户高并发访问的情况下,如何做到库存有效扣减,避免未锁定库存时导致数据库数据不一致。 进行了模板类单步控制执行,数据库进行了可重复读控制
a、 可重复读(Repeatable Read,RR)
b、读稳定性(Read Stability,RS)
c、游标稳定性(Cursor Stability,CS)
d、未提交读(Uncommitted Read,UR)
1、可重复读(RR -- Repeatable Read)
a、可重复读隔离级别是最严格的隔离级别。在使用它时,一个事务的影响完全与其他并发事务隔离:脏读、不可重复读、幻像读都不会发生。
当使用可重复读隔离级别时,在事务执行期间共享(S)锁定该事务以任何方式引用的所有行。因此,如果在同一个事务中发出同一个SELECT语
句两次或更多次,那么产生的结果数据集总是相同的。因此,使用可重复读隔离级别的事务可以多次检索同一行集,并可以对它们执行任意操作,
直到由提交或回滚操作终止事务。但是,在事务存在期间,不允许其他事务执行会影响该事务正在访问的任何行的插入、更新或删除操作。为了确保这种行为,
锁定该事务所引用的每一行 -- 而不是仅锁定被实际检索或修改的那些行。因此,如果一个表中有1000行,但只检索两行,则整个表(1000行,而不仅是被检索的两行)
都会被锁定。
b、如果使用可重复读隔离级别,不管从表中读多少数据,整个表上都加S锁,直到该事务被提交或回滚,表上的锁才会被释放。
这样可以保证在一个事务中即使多次读取同一行,得到的值也不会改变。另外,在同一个事务中如果以同样的搜索标准重新打开已被处理过的游标,
那么得到的结果集不会改变。可重复读相对于读稳定性而言,加锁的范围更大。对于读稳定性,应用程序只对符合要求的所有行加锁,而对于可重复读,
应用程序将对整个表都加S锁。
c、可重复读(RR),不可能出现丢失更新、脏读和幻像读的情况;
2、读稳定性(RS -- Read Stability)
a、读稳定性隔离级别没有可重复读隔离级别那么严格。读稳定性(RS)可以防止脏读和不可重复读,但可能出现幻像读。在使用这个隔离级别时,
只锁定事务实际检索和修改的行。因此,如果一个表有1000行,但只检索两行(通过索引扫描),则只有被检索的两行(而不是所扫描的1000行)
被锁定。因此,如果在同一个事务中发出同一个select语句多次,那么每次产生的结果集可能不同。
b、与可重复读隔离级别一样,在读稳定性隔离级别下运行的事务可以检索一个行集,并可以对它们执行任意操作,直到事务终止。
在这个事务存在期间,其他事务不能执行那些会影响这个事务检索到的行集的更新或删除操作(其他事务可以更新或删除 不影响该事务检索到的行集的数据);
但是其他事务可以执行插入操作。如果插入的行与第一个事务的查询的选择条件匹配,那么这些行可能作为幻像出现在后续产生的结果数据集中。
其他事务对其他行所作的更改,在提交之前是不可见的。
c、如果使用读稳定性(RS)这种隔离,在一个事务中将有N+1个锁,其中N是所有被读取(通过索引扫描)过的行的数目,这些行上都会被加上NS锁,
在表上加1个IS锁。这些锁直到事务被提交或回滚,才会被释放。这样可以保证在一个事务中即使多次读取同一行,得到的值不不会改变。但是,使用读稳定性,
在一个事务中,如果使用同样的搜索标准重新打开已被处理过的游标,那么结果集可能改变(可能会增加某些行,这些行被称为幻影行-Phantom)。
这是因为RS不能阻止通过插入或更新操作在结果集中加入新行。
d、读稳定性(RS),只锁定应用程序在工作单元中检索的那些行。它确保在某个工作单元完成之前,在该工作单元运行期间的任何限定行读取不被其他应用程序进程更改,
且确保不会读取由另一个应用程序所更改的任何行,直到该进程提交了这些更改。读稳定性,不可能出现“不可重复读”情形。
e、“读稳定性”,其中一个目标是提供较高的并行性程度以及数据的稳定视图。为了有助于达到此目的,优化器确保在发生锁定升级前不获取表级锁定。
f、“读稳定性”隔离级别最适用于包括下列所有特征的应用程序:
在并发环境下运行;需要限定某些行在工作单元运行期间保持稳定;在工作单元中不会多次发出相同的查询,或者在同一个工作单元中发出多次查询时,
并不要求该查询获得相同的回答。
3、游标稳定性(CS -- Cursor Stability)
a、游标稳定性隔离级别,可以防止脏读,但有可能出现不可重复读和幻像读。游标稳定性只锁定事务声明并打开游标当前引用的行。
b、当使用游标稳定性隔离级别时,事务通过游标从表中检索行时,其他事务不能更新或删除游标所引用的行。但是,如果被锁定的行本身不是用索引访问的,
那么其他事务可以将新的行添加到表中,以及对被游标锁定行前后的行进行更新和删除操作。所获取的锁一直有效,直到游标重定位或事务终止为止
(如果游标重定位,原来行上的锁就被释放,并获得游标现在引用的行上的锁)。此外,如果事务修改了它检索到的任何行,那么在事务终止之前,
其他事务不能更新或删除改行,即使游标不再位于被修改的行。例如:一个表中有1000行数据,我们只检索其中的两行数据,那么对于可重复读(RR)
隔离级别会锁住整个表;读稳定性(RS)会对读到的数据(两行)加锁;游标稳定性(CS)隔离级别只对游标当前所在的那一行加锁,游标所在行的前一行和下一行都不加锁。
c、结果集中只有正在被读取的那一行(游标指向的行)将被加上NS锁,在表上加IS锁。其他未被处理的行上不被加锁。CS只能保证正在被处理的行的值不
会被其他并发的程序所改变。
d、当在行上定位游标时,游标稳定性CS会锁定任何由应用程序的事务所访问的行。此锁定在读取下一行或终止事务之前有效。但是,如果更改了某一行上的任何数据,
那么在对数据库提交更改之前必须挂起该锁定。
e、对于具有“游标稳定性”的应用程序已检索的行,当该行上有任何可更新的游标时,任何其他应用程序都不能更新或删除该行。“游标稳定性”应用程
序不能查看其他应用程序的未提交更改。
f、与可重复读(RR)和读稳定性(RS)隔离级别一样,其他事务在其他行上进行的更改,在这些更改提交之前对使用游标稳定性(CS)
隔离级别的事务(这时默认的隔离级别)来说是不可见的。
g、游标稳定性,可能会出现不可重复读和幻像读现象。
4、未提交读(UR - Uncommitted Read)
a、未提交读隔离级别是最不严格的隔离级别。实际上,在使用这个隔离级别时,仅当另一个事务试图删除或更改被检索的行所在表时,
才会锁定这个事务检索的行。因为在使用这种隔离级别时,行通常保持未锁定状态,使用脏读、不可重复读和幻像读都可能会发生。因此,
未提交读通常用于访问只读表和视图的事务,以及某些执行select语句的事务。
b、未提交读UR,运行应用程序读取其他事务未落实的更改。但是对于只读和可更新两种不同的游标类型而言,UR的工作方式有所不同。
对于可更新的游标,当它使用隔离级别UR运行程序时,应用程序会自动使用隔离级别CS。
c、使用UR,对于只读操作,不加行锁。典型的只读操作包括:SELECT语句的结果集只读(比如语句中包括ORDER BY子句);
定义游标时指明FOR FETCH ONLY或FOR READ ONLY。
d、UR,最大程度上允许并发;若需读取未提交的数据,该隔离级别是唯一选择。
e、只读游标可访问大多数其他事务的未提交的更改。但是,当该事务正在处理时,不能使用正由其他事务创建或删除的表、视图和索引。
其他事务的任何其他更改在提交或回滚前都可被读取。
DB2默认的隔离级别为:游标稳定性(CS)
8. 在项目中遇到了哪些问题,自己是如何解决的
项目涉及的周边系统比较多,这个时候就需要按照优先级先进行分类,并将自己需要等待解决的问题一一罗列出来,然后逐个按照紧急程度逐个找接口人解决。
9. 说一下有哪些常用的设计模式
1、 工厂模式:
客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工
厂类也要做相应的修改。如:如何创建及如何向客户端提供。
2、建造模式:
将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。
建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
3、工厂方法模式:
核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现
的接口,而不接触哪一个产品类应当被实例化这种细节。
4、原始模型模式:
通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动
态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
5、单例模式:
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
6、适配器(变压器)模式:
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
7、桥梁模式:
将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化
之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
8、合成模式:
合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的
关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。
9、装饰模式:
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些
功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
10、门面模式:
外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只
有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。
11、享元模式:
FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状
态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相
互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,
而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
12、代理模式:
代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构
采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象
与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象
必须有系统的其他角色代为创建并传入。
13、责任链模式:
在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处
理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:
承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。
14、命令模式:
命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式
允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被
执行以及是怎么被执行的。系统支持命令的撤消。
15、解释器模式:
给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中
的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的
任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对
象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。
16、迭代子模式:
迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够
包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象
都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
17、调停者模式:
调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用
发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。
调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
18、备忘录模式:
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,
并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
19、观察者模式:
观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知
所有观察者对象,使他们能够自动更新自己。
20、状态模式:
状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,
每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
21、策略模式:
策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影
响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开
来,算法的增减,修改都不会影响到环境和客户端。
22、模板方法模式:
模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。
不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
23、访问者模式:
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。
访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问
者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者 模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类
中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不
同的等级结构的成员类。
10. 事务有哪些特性,在ORACLE中隔离有哪些级别
一.什么是事务
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,
一个事务中的一系列的操作要么全部成功,要么一个都不做。
事务的结束有两种,当事务中的所以步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消撤消之前到事务开始时的所以操作。
二.事务的 ACID
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。
如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,
这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
1、脏读取(dirty read):一个事务读取了被其他事务写入但还未提交的数据。
2、不可重复读取(nonrepeatable read):一个事务再次读取其之前曾经读取过的数据时,发现数据已被其他已提交的事务修改或删除。
3、不存在读取(phantom read):事务按照之前的条件重新查询时,返回的结果集中包含其他已提交事务插入的满足条件的新数据。
ANSI/ISO SQL 标准(SQL92)定义了四种事务隔离级别(transaction isolation level)
现象隔离级别 脏读取 不可重复读取 不存在读取
未提交读取(read uncommitted) 允许 允许 允许
已提交读取(read committed) 不允许 允许 允许
可重复读取(repeatable read) 不允许 不允许 允许
串行化(rerializable) 不允许 不允许 不允许
Oracle 支持三种事务隔离级别:已提交读取,串行化,以及 SQL92 中没有包含的只读模式(read-only mode)。
已提交读取是 Oracle 默认使用的事务隔离级别。
Oracle 支持以下三种事务隔离级别(transaction isolation level)。
隔离级别 描述
已提交读取 Oracle 默认使用的事务隔离级别。事务内执行的查询只能看到查询执行前(而非事务开始前)就已经提交的数据。
Oracle 的查询永远不会读取脏数据(未提交的数据)。Oracle 不会阻止一个事务修改另一事务中的查询正在访问的数据,
因此在一个事务内的两个查询的执行间歇期间,数据有可能被其他事务修改。举例来说,如果一个事务内同一查询执行两次,
可能会遇到不可重复读取或不存在读取的现象。
串行化 串行化隔离的事务只能看到事务执行前就已经提交的数据,以及事务内 INSERT , UPDATE ,及 DELETE 语句对数据的修改。
串行化隔离的事务不会出现不可重复读取或不存在读取的现象。
只读模式 只读事务只能看到事务执行前就已经提交的数据,且事务中不能执行 INSERT , UPDATE ,及 DELETE 语句。
已提交读模式:SET TRANSACTION ISOLATION LEVEL=READ COMMITTED;
串行模式:SET TRANSACTION ISOLATION LEVEL= SERIALIZABLE;
只读模式:SET TRANSACTION= READ ONLY;
(经笔者实验以上命令在非sysdba用户下可以成功执行,sysdba下不能执行,待验证正确性)
如果在每个事务开始时都使用 SET TRANSACTION 语句,将加重网络及处理器的负担。用户可以使用 ALTER SESSION 语句 改变一个会话所有内事务的默认隔离级别:
1、ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
2、ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
11. 使用memcached是一个什么样的原理
Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。
同时,memcached用的是一个二级散列,通过一张大hash表来维护。Memcached有两个核心组件组成:服务器端(server)和客户端(client),
在一个memcached的查询中,client先通过计算key的hash值来确定kv对所处在的server位置。当server确定后,客户端就会发送一个查询请求给对应的server,
让它来查找确切的数据。因为这之间没有交互以及多播协议,所以memcached交互带给网络的影响是最小化的。
12. Memcached的内存管理机制
memcached会预先分配内存,首先,这里有3个概念:
1. slab
2. page
3 . chunk
解释一下,一般来说一个memcahced进程会预先将自己划分为若干个slab,每个slab下又有若干个page,每个page下又有多个chunk,
如果我们把这3个咚咚看作是object得话,这是两个一对多得关系。再一般来说,slab得数量是有限得,几个,十几个,或者几十个,
这个跟进程配置得内存有关。而每个slab下得page默认情况是1m,也就是说如果一个slab占用100m得内存得话,那么默认情况下这个slab
所拥有得page得个数就是100,而chunk就是我们得数据存放得最终地方。
Chunk用于缓存记录的内存空间。
Slab Class :特定大小的chunk的组。
Memcached的内存分配以page为单位,默认情况下一个page是1M ,可以通过-I参数在启动时指定。如果需要申请内存 时,memcached会划分出一个
新的page并分配给需要的slab区域。Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责
一定范围内的数据存储,其大小可以通过启动参数设置增长因子,默认为1.25,即下一个slab的大小是上一个的1.25倍。如 下图,每个slab只存储
大于其上一个slab的size并小于或者等于自己最大size的数据。如下图所示,需要存储一个100Bytes的对象时,会选用112Bytes的Slab Classes
六.Memcached的缓存策略
当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端
由app设置并作为参数传给ms的。
同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。
七.Memcached的客户端
Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等。其中面向Java的三种Memcached客户端包括memcached client for java、
spymemcached和xmemcached 。
13. 如何存放数据到memcached集群中
14. 一致性哈希算法的实现原理。
15. JVM中堆是如何管理的,JVM的内存回收机制
堆内存是内存中最重要的一块,因为Java性能的优化,主要就是针对这部分内存的。所有的对象实例及数组都是在堆上面分配的
判断哪些对象可回收:
GC是通过对象是否存活来决定是否进行回收,判断对象是否存活主要有两种算法:引用计数算法、可达性分析算法
•引用计数算法
引用计数的算法原理是给对象添加一个引用计数器,每被引用一次计数器加1,引用失效时减1,当计数器0后表示对象不在被引用,可以被回收了,引用计数法简单高效,但是存在对象之间循环引用问题,可能导致无法被GC回收,需要花很大精力去解决循环引用问题
•可达性分析算法
可达性分析的算法原理是从对象根引用(堆栈、方法表的静态引用和常量引用区、本地方法栈)开始遍历搜索所有可到达对象,形成一个引用链,遍历的同时标记出可达对象和不可达对象,不可达对象表示没有任何引用存在,可以被GC回收
如何回收:
找到可回收对象后,如何进行回收呢?
内存回收算法主要有标记-清除、停止-复制、标记-整理,不同算法使用不同的场景,总体来说停止-复制算法适合对象存活时间短,存活率低的新生代,标记-清楚和标记-整理算法适合对象存活时间长,存活率高的老年底
•标记-清除(Mark-Sweep)
通过可达性分析算法标记所有不可达对象,然后清理不可达对象。这种算法会形成大量的内存碎片
•停止-复制(Stop-Copy)
将新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区,回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复,当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代(这时我们可能回想,若是老年代也满了咋办,若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收,若是内存还不够呢。。。,还不够那不废话了吗,OutOfMemory,不陌生吧哈哈)。从停止-复制算法的原理上我们可以看到,这种算法对于存活率较低的对象回收有着非常高的效率,而且不会形成内存碎片,但是会浪费一定的内存空间,适合对象存活率较低的新生代使用,如果在对象存活率较高的老年代采用这种算法,那将会是一场灾难
•标记-整理(Mark-Compact)
通过可达性分析算法标记所有不可达对象,然后将存活对象都向一个方向移动,然后清理掉边界外的内存。这种算法是将存活对象向着一个方向聚集,然后将剩余区域清空,这种算法适合对象存活率较高的老年代
GC回收机制:分代收集算法:
JVM内存收集算法基本上都是采用分代收集算法,即将内存划分为新生代、老年代,也有人把方法区算做永久代
•新生代
对象被创建时,内存分配都是发生在新生代(大对象直接分配在老年代),绝大多数对象都是朝生夕灭,创建后很快就会不在使用,变为不可达的对象,被GC回收掉。新生代的对象存活率很低(到底有多低?研究表明有高达98%的对象创建后很快就消亡,想象一下平时编程,除了全局变量,局部变量在退出调用方法后还有几个能存活),存活时间都很短,新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)
•老年代
当对象在新生代发生了多次Minor GC后仍然存活的对象即进入老年代,老年代的对象比新生多很多,当然了内存比新生代也大很多(大概比例是1:2,即新生代占用堆内存总量的1/3),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高
一般来说我们所说的GC都是发生在新生代和老年代,新生代对象存活时间短,存活率低一般采用停止-复制算法,老年代对象存活时间长,存活率高,一般采用标记-整理、标记-清楚算法,具体采用何种算法和具体采用的垃圾收集器有关
GC里面有些类似未成年人和成年人,新创建的对象为新生代,新生代想要成为老年代需要经过一定的成长(总得一点点长大是吧),新创建的对象年龄为1,每发生一次Minor GC,存活对象的年龄增加1,当经历了15次Minor GC后,仍然存活的对象达到15岁,成达到法定成年年龄15岁(默认是15),正式成为成年人(老年代),对象成年后也就没有了年龄概念,直到对象死亡,会一直呆在老年代,当然也有一些老不死的(静态变量、常量等),会与世长存,除非地球灭亡(GC崩溃)
GC收集器:
GC采用分代回收算好后,起着重要作用的是GC收集器,GC收集器分为新生代收集器和老年代收集器,不同的收集器使用不同的收集算法,有着不同的特点,由于目前的收集器在内存回收时无法消除(Stop-the-world),即在回收内存时不可避免的停止用户线程,目前的收集器只能使停顿时间越来越短,但是无法彻底消除,主要的收集其中Parallel Scavenge和Parallel Old是追求吞吐量为目标,其它的收集器都是追求高响应,低停顿,
新生代收集器:Serial、PraNew、Parallel Scavenge
老年代收集器:Serial Old、Parallel Old、CMS
•Serial收集器(复制算法)
新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
•Serial Old收集器(标记-整理算法)
老年代单线程收集器,Serial收集器的老年代版本。
•ParNew收集器(停止-复制算法)
新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
•Parallel Scavenge收集器(停止-复制算法)
并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。
•Parallel Old收集器(停止-复制算法)
Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先
•CMS(Concurrent Mark Sweep)收集器(标记-清理算法)
高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择
•G1(Garbage-First)收集器(标记-整理算法、停止复制算法)
GC最新型号,高富帅,高并发、可预测停顿、分代收集,不出意外未来主流将会逐步替代CMS,g1模糊了分代概念,虽然还是分为新生代和老年代,但是新生代和老年代不再是物理隔离,而是将内存分为n个region,以region为清理单位,整体采用标记-整理算法,region内部使用停止-复制算法。
16. spring的aop的实现方法
17. 分布式消息队列,分布式缓存
18. rpc方面
19. hashmap源码实现
20. Java异常的续承层次结构,讲述异常的续承关系
21. https握手过程
1、客户端浏览器给服务器发送自己支持的对称、非对称加密算法和摘要函数列表以及一个随机数。
2、服务器收到客户端的请求后选择特定的加密算法和摘要函数以及生成一个随机数,外加自己的证书发送给客户端。
3、客户端收到后先验证证书,如果证书受信就继续,否则终止。客户端从证书中获取到服务器的加密公匙,然后浏览器产生一个随机字符串作为pre-master-securet然后用服务器的公匙加密后发给服务器,告诉服务器说在后续的对称加密过程中会使用这个密匙。
4、服务器收到后用自己的私匙解密得到pre-master-securet,然后用一定的加密算法生成一个master-securet,然后加密后发给客户端,告诉客户端以后对称加密使用这个密匙。
22. java数据库问题定位和性能调优
23. 怎么量化分析链接池里的链接数配置事物
24. 如何量化分析还是要看上线后在线用户数
a、品牌
品牌包括在网站中所有审美的、设计相关的项目。它带给网站想要的组织形象或信息的创意。用于测量品牌的描述包括:
网站提供给访客有吸引力的和难忘的体验
网站的视觉效果与品牌特征保持一致
图像、附加内容和多媒体对于体验的增值
网站传达出品牌的感知预示
网站利用了媒体的能力来增强和扩展品牌
b、功能
功能包括所有技术方面的和“后台的”进程和应用。它让网站提供给所有最终用户交互式的服务,而且重要的是,注意这有的时候同时意味着前台公众用户和后台管理员。网站功能的描述包括:
用户及时获得对他们查询和提交信息的响应
任务进程的清晰告知(比如,成功页面或邮件更新提示)
网站和应用严格遵守通用的安全和隐私标准
在线功能与离线业务流程结合
网站包含管理员工具来加强管理员的效率
c、可用性
可用性带来的是所有网站元素和特性的总体易用性。可用性之下的二级主题包括导航和易用性(友好度)(注释:易用性处理的是使在线内容可用于用户的体验,享受和使用的问题)。可用性的描述包括:
网站防止错误发生,并帮用户从错误中恢复
整体网页侧重针对主要受众优化
网站帮助访问者达成一般目标和任务
网站遵循它自己的一致性和标准
网站为残疾用户提供内容
d、内容
内容指的是网站的实际内容(文本,多媒体,图像)及其结构,或信息架构。我们来看信息和内容是如何按照定义的用户需要和客户的商业需求组织的。测量内容的描述包括:
链接密度有足够的清晰度,且容易导航
内容组织方便用户达到目标
内容及时准确
内容适合客户需要和商业需求
多语言的综合性内容
在多数情况下,我会为这四种元素分别使用10到20个独立的描述。我建议你使用如上描述作为你创建你自己的分析的基础。请记住,如果你添加了更多的描述,你必须也调整20分的尺度,以便每个元素的总分为100。例如,如果你为每个元素使用10个描述,那么你的评分尺度应该是1-20。如果你为每个元素使用20个描述,你的尺度应该是1-5。
25. CORE文件详细怎么分析
在Unix系统下,应用程序崩溃,一般会产生core文件,可以根据core文件查找问题的所在,并做相应的分析和调试,是非常重要的。
就可以利用命令gdb进行查找,参数一是应用程序的名称,参数二是core文件,运行gdb
Core的意思是内存, Dump的意思是扔出来, 堆出来.
开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.
如何使用core文件?
gdb -c core文件路径 [应用程序的路径]
进去后输入where回车, 就可以显示程序在哪一行当掉的, 在哪个函数中.
为什么没有core文件生成呢?
有时候程序down了, 但是core文件却没有生成. core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便成生成core文件.
ulimit -c unlimited
core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号
26. JVM的堆是怎么规划的
http://blog.csdn.net/lifuxiangcaohui/article/details/37992725