总结1
周末了,来总结一下这两周所学到的知识。
各种琐碎:(1)java中的HashTable,Vector,TreeSet,LinkedList哪个线程是安全的?(HashTable, Vector是线程安全的)安全不安全,关键是看是看多线程情况下和单线程情况下运行的结果是否一样。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了,呵呵。
ps:关于java中的各种容器,见http://zhhxxx.iteye.com/blog/654048
(2)JDBC事务隔离级别有几种?(5种,想一下哪5种?)
JDBC的数据隔离级别设置:
JDBC | 数据库隔离级别 | 数据访问情况 |
TRANSACTION_READ_UNCOMMITTED | ur | 就是俗称“脏读”(dirty read),在没有提交数据时能够读到已经更新的数据。 |
TRANSACTION_READ_COMMITTED | cs | 在一个事务中进行查询时,不允许读取提交前的数据,数据提交后,当前查询就可以读取到数据。update数据时候并不锁住表。 |
TRANSACTION_REPEATABLE_READ | rs | 在一个事务中进行查询时,不允许读取其他事务update的数据,允许读取到其他事务提交的新增数据。 |
TRANSACTION_SERIALIZABLE | rr | 在一个事务中进行查询时,不允许任何对这个查询表的数据修改。 |
JDBC事务隔离级别
为了解决与“多个线程请求相同数据”相关的问题,事务之间用锁相互隔开。多数主流的数据库支持不同类型的锁;因此,JDBC API 支持不同类型的事务,它们由 Connection 对象指派或确定。在 JDBC API 中可以获得下列事务级别:
TRANSACTION_NONE 说明:
不支持事务。
TRANSACTION_READ_UNCOMMITTED 说明:
在提交前一个事务可以看到另一个事务的变化。这样脏读、不可重复的读和虚读都是允许的。
TRANSACTION_READ_COMMITTED 说明:
读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和虚读产生。
TRANSACTION_REPEATABLE_READ 说明:
事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。
TRANSACTION_SERIALIZABLE 是最高的事务级别,它防止脏读、不可重复的读和虚读。
(ps:虚读 phantom read:如果符合搜索条件的一行数据在后面的读取操作中出现,但该行数据却不属于最初的数据,就会发生这种事件。举例来说:Transaction1读取满足某种搜索条件的一些行,然后Transaction2 插入了符合Transaction1的搜索条件的一个新行。如果 Transaction1 重新执行产生原来那些行的查询,就会得到不同的行。)
为了在性能与一致性之间寻求平衡才出现了上面的几种级别。事务保护的
级别越高,性能损失就越大。
假定您的数据库和 JDBC 驱动程序支持这个特性,则给定一个 Connection 对象。
您可以明确地设置想要的事务级别:
conn.setTransactionLeve (TRANSACTION_SERIALIZABLE);
可以通过下面的方法确定当前事务的级别:
int level = conn.getTransactionIsolation(); if(level == Connection.TRANSACTION_NONE) System.out.println("TRANSACTION_NONE"); else if(level == Connection.TRANSACTION_READ_UNCOMMITTED) System.out.println("TRANSACTION_READ_UNCOMMITTED"); else if(level == Connection.TRANSACTION_READ_COMMITTED) System.out.println("TRANSACTION_READ_COMMITTED"); else if(level == Connection.TRANSACTION_REPEATABLE_READ) System.out.println("TRANSACTION_REPEATABLE_READ"); else if(level == Connection.TRANSACTION_SERIALIZABLE) System.out.println("TRANSACTION_SERIALIZABLE");
(3)关于Spring的一些名词
Spring实际上是一个开源框架(是一种轻量级容器),主要优势之一是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情(即用JavaBean代替EJB)。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
ps:EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。
特点:网络服务支持和核心开发工具(SDK)。在J2EE中,EJB成为Java企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。
具体参见:http://baike.baidu.com/view/3542.htm
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
1)IoC(本质为反射):控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题。
IoC不是什么技术,与GoF一样,是一种设计模式。
IoC将对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单,只要修改XML就可以了。
实现策略
把字节序列恢复为Java对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
(8)实现Webservice的几个框架:Axis,Xfire,Apache CXF,貌似struts不是。。。