杂乱知识点
事务属性的种类: 传播行为、隔离级别、只读和事务超时
a) 传播行为定义了被调用方法的事务边界。
传播行为 | 意义 |
PROPERGATION_MANDATORY | 表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常 |
PROPAGATION_NESTED | 表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和PROPAGATION_REQUIRED 看起来没什么俩样 |
PROPAGATION_NEVER | 表示方法不能运行在一个事务中,否则抛出异常 |
PROPAGATION_NOT_SUPPORTED | 表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起 |
PROPAGATION_REQUIRED | 表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务 |
PROPAGATION_REQUIRES_NEW | 表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起 |
PROPAGATION_SUPPORTS | 表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中 |
b) 隔离级别
在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。为了避免这 3 中副作用的发生,在标准的 SQL 语句中定义了 4 种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别来对应在SQL 中定义的 4 种隔离级别,如下:
隔离级别 | 意义 |
ISOLATION_DEFAULT | 使用后端数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读 |
ISOLATION_READ_COMMITTED | 允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读 |
ISOLATION_REPEATABLE_READ | 一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读 |
ISOLATION_SERIALIZABLE | 这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。 |
c) 只读
如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 。
因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为(PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。
如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。
d) 事务超时
如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设
置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
注意以下几点:
- 1.service方法是在servlet生命周期中的服务期,默认在HttpServlet类中实现,根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法实现。
- 2.GenericServlet 抽象类给出了设计servlet的一些骨架,定义了servlet生命周期还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的。doget/dopost与Http协议有关,是在 javax.servlet.http.HttpServlet 中实现的。
- 3.doGet和doPost方法在HttpServlet类中实现,GenericServlet中实现了service()
- 4.常说所有的请求都先由service方法处理,而javax.servlet.GenericServlet接口实现了javax.servlet.Servle接口,且javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子类。只有最先定义好了的service方法才可以处理所有的请求。
Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。
- 加载:Servlet容器(Tomcat)通过类加载器加载servlet文件(.class)
- 创建:通过调用servlet构造函数创建一个servlet对象
- 初始化:调用init方法初始化
- 处理客户请求:每当有一个客户请求,容器会创建一个线程,调用service方法来处理客户请求
- 卸载:调用destroy方法让servlet自己释放其占用的资源
servlet是由Servlet容器负责加载Servlet类,创建Servlet对象并实例化,然后调用Servlet的init方法,进行初始化,之后调用Service方法。实例化和初始化不同。先实例化,再初始化。
serlvet是单实例多线程(servlet在多线程下其本身并不是线程安全的。)
如果在类中定义成员变量,而在service中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
来看4个选项:
A: a == b
由图可以看出a和b指向的不是同一个引用,故A错
B:s == a
一个Square类型不能与一个long型比较,编译就错误,故B错
c:b == c
由图可以看出b和c指向的是同一个引用,故C正确
d:a equal s
程序会把s封装成一个Long类型,由于Square没有重写Object的equals方法, 所以调用的是Object类的equals方法,源码如下
1 2 3 |
|
其实就是判断两个引用是否相等,故D也错误。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
答案:C
JVM中一个字节以下的整型数据会在JVM启动的时候加载进内存,除非用new Integer()显式的创建对象,否则都是同一个对象所有只有i04是一个新对象,其他都是同一个对象。所有A,B选项为true
Integer i01=59 的时候,会调用 Integer 的 valueOf 方法,
public static Integer valueOf(int i) {
assert IntegerCache.high>= 127;
if (i >= IntegerCache.low&& i <= IntegerCache.high)
return IntegerCache.cache[i+ (-IntegerCache.low)];
return new Integer(i); }
这个方法就是返回一个 Integer 对象,只是在返回之前,看作了一个判断,判断当前 i 的值是否在 [-128,127] 区别,且 IntegerCache 中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。
在这里的话,因为程序初次运行,没有 59 ,所以,直接创建了一个新的对象。
int i02=59 ,这是一个基本类型,存储在栈中。
Integer i03 =Integer.valueOf(59); 因为 IntegerCache 中已经存在此对象,所以,直接返回引用。
Integer i04 = new Integer(59) ;直接创建一个新的对象。
System. out .println(i01== i02); i01 是 Integer 对象, i02 是 int ,这里比较的不是地址,而是值。 Integer 会自动拆箱成 int ,然后进行值的比较。所以,为真。
System. out .println(i01== i03); 因为 i03 返回的是 i01 的引用,所以,为真。
System. out .println(i03==i04); 因为 i04 是重新创建的对象,所以 i03,i04 是指向不同的对象,因此比较结果为假。
System. out .println(i02== i04); 因为 i02 是基本类型,所以此时 i04 会自动拆箱,进行值比较,所以,结果为真。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------
-Xmx:最大堆大小
-Xms:初始堆大小
-Xmn:年轻代大小
-XXSurvivorRatio:年轻代中Eden区与Survivor区的大小比值
年轻代5120m, Eden:Survivor=3,Survivor区大小=1024m(Survivor区有两个,即将年轻代分为5份,每个Survivor区占一份),总大小为2048m。
-Xms初始堆大小即最小内存值为10240m
----------------------------------------------------------------------------------------------------------------------------------------------------------------