目录
1.3 为什么需要publicstatic void main(String args[])
1.4 如何实现在main() 函数执行前输出“Hello World!”
2.8 抽象类(abstractclass) 和接口(interface) 的异同
3.2 break , continue和 return 的区别
3.3 final、finally 和finalize 的区别
4.7 Math 中的round、ceil 和 floor 方法的功能
5.2 “==”、“equals”和 hashcode 的区别
5.3 String、StringBuffer、StringBuilder和StringTokenizer的区别
8.4 GC 垃圾回收机制(Garbage Collection,GC)
9.3 ArrayList、Vector和LinkedList
9.4 HashTable,HashMap,TreeMap和WeakHashMap
9.5 自定义的HashMap 和HashTable的key需要注意
11.4 Statement、PreparedStatement 、CallableStatement
11.5 getString() 方法和getObject()方法
一、基本概念
1.1 Java语言的优点
1)Java 为纯面向对象的语言;
2)与平台无关;
3)Java提供了很多内置的类库;
4)提供了对web 应用开发的支持;
5)具有较好的安全性和健壮性;
6)去除了C++ 中的一些难以理解,容易混淆的特性。
1.2 Java 与C++ 的异同
相同点:Java和C++ 都是面向对象的语言
不同点:
1) Java为解释性语言,C/C++ 为编译性语言;
2) Java为纯面向对象的语言,C++ 兼有面对对象和面向过程的特点;
3) 与C++ 相比,Java不支持多重继承;(但是Java有接口)
4) Java没有指针的概念;
5) Java有自动垃圾回收机制。(finalize()方法,当垃圾回收机制准备回收无用对象的内存时,会首先调用该对象的finalize()方法)
1.3 为什么需要publicstatic void main(String args[])
java程序的入口,JVM在运行的时候,会先查找main() 函数。
1.4 如何实现在main() 函数执行前输出“Hello World!”
使用静态模块,静态模块在类加载的时候就会被调用。
1.5 Java程序的初始化的顺序是怎样的
Java在示例化对象是,首先要进行初始化,初始化遵守三个原则:
1) 静态变量优先于非静态变量,但是静态变量只会初始化一次;
2) 父类优先于子类进行初始化;
3) 按照成员变量的定义顺序进行初始化,总是在任何方法被调用之前初始化。
1.6 Java中的作用域有哪些
三种变量类型:成员变量,静态变量,局部变量
成员变量有四种作用域:public,protected, default,private
对应:当前类,同一package,子类,其他package;
public, abstract,final才能用来修饰类。
1.7一个Java文件中是否可以定义多个类
只有一个被public或者没有public修饰的类。
1.8什么是构造函数
和类名相同的,没有返回值的函数,不能被继承,所以不能被覆盖,但是能够多写几个参数不同的构造函数,即能够重载,总是伴随着new产生构造函数。
1.9为什么Java有些接口中没有任何方法
Java不支持多重继承,所以引入了接口的概念,接口是抽象方法定义的集合,接口中只包含方法的定义,没有方法的实现,接口中所有的方法都是抽象的,接口中成员的作用域修饰符都是public,接口中常量值默认使用public static final修饰。
没有申明任何方法的接口为标识接口,譬如:Cloneable 和 Serializable等。
1.10 Java中的clone 方法有什么作用
Java中的所有类都默认继承自object类,而object类中提供了一个clone()方法,返回一个object对象的复制,这个赋值函数返回的是一个新的对象而不是引用。
存在的深复制与浅复制,被赋值的对象中只含有基本类型的书籍时,只需要浅复制就可以。如果被赋值的类中包含了一些对象,就需要深复制了,实现方式是对对象调用clone() 方法完成复制。
浅复制:浅复制仅仅复制所考虑的对象,而不赋值它引用的对象。
深复制:被赋值有变量都含有与原来对象相同的值,而被赋值对象所引用的对象,都被复制成了新对象。
1.11什么是反射机制
得到一个对象所属的类;获取一个类的所有成员变量和方法;在运行时创建对象;在运行时调用对象的方法。à 在运行时动态地创建类的对象。
1.12 package 有什么作用
一、提供多层命名空间,解决命名冲突问题。
二、对类按功能进行分类,使项目的条理更加清晰。
1.13 如何实现类似C语言中的函数指针的功能
可以利用接口与类来实现:先定义一个接口,然后在接口中声明要调用的方法,接着实现这个接口,最后吧这个实现类的一个对象作为参数传递给调用程序。
interface IntCompare{ public int cmp(int a , int b);}
class Cmp1 implements IntCompare {
publicint cmp (int a, int b ){
if(a>b)return 1;
elseif(a<b) return -1;
elsereturn 0;
}
}
二、面对对象技术
2.1 面对对象和面对过程有什么区别
1)出发点不同
2)层次逻辑关系不同
3)数据处理方式和控制程序方式不同
4)分析设计和编码转换方式不同
2.2 面对对象有哪些特征
抽象,继承,封装,多态
2.3 面对对象开发方式的优点
1)较高的开发效率
2)保证软件的鲁棒性
3)保证软件的高可维护性
2.4 继承 class Aextends B
1)Java不支持多重继承,但是可以通过接口来实现
2)覆盖:子类和父类重名时会覆盖
2.5 组合和继承的区别
继承:A is a B ; 组合 : A has a B;
code: extends
class Vehicle{}
class Car extends Vehicle {}
组合
class Tire{}
class Car extends Vehicle{
privateTire t = new Tire();
}
2.6 多态的实现机制是什么
1)方法的重载(overload) 同名不同参数à 编译时动态
2)方法的覆盖(override) 子类继承父类,对同样的方法重写
编译时的多态是通过重载来实现,运行时的多态是通过方法的覆盖来实现的。
2.7 重载和覆盖的区别
1)重载通过不同的参数来区分
2)覆盖的时候需要方法名相同,参数相同
2.8 抽象类(abstractclass) 和接口(interface) 的异同
因为只能继承一个,但是有的类需要扩展好几个属性,所以提出了接口。
相同点:
都不能被实例化;接口的实现类或者抽象类的子类只有实现了接口或者抽象类中的方法后才能被实例化。
不同点:
接口只有定义,但是抽象可以有定义和实现;
接口需要实现(implements),但抽象类只能被继承(extends),多个实现,一个继承
接口à has-a 抽象 is-a
接口中定义成员变量默认为public static final , 必须赋初值,
使用:当功能需要积累时,用抽象类,当功能不需要积累时,用接口。接口被运用于实现比较常用的功能,抽象类更倾向于充当公共类的作用。
2.9 内部类有哪些
静态内部类:
class outerClass{
staticclass innerClass{}
}
成员内部类:
class outerClass{
classinnerClass{}
}
局部内部类:
class outerClass{
publicvoid memberFunction(){
classinner innerClass{}
}
}
匿名内部类:
public class MyFrame extends Frame(){
publicmyFrame(){
addWindowListener(newWindowsAdapter() {
publicvoid windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
}
}
2.10 如何获取父类的类名
获取类名的方法:class.getClass().getName();
获取父类类名的方法:class.getClass().getSuperclass().getName();
2.11 this 与super 有什么区别
this用来指代当前实例对象,区分对象的成员变量与方法的形参;(当方法形参与成员变量的名字相同时,会覆盖成员变量。
super可以访问父类的方法或者成员变量
三、关键字
3.1 变量命名规则
只能由字母,数字,下划线和$组成,并且标识符的第一个字符不能是数字,不能包含空白字符,不能是保留字。
3.2 break , continue和 return 的区别
break:直接跳出当前循环,不再执行剩余代码
continue:停止当前循环,回到循环起始处
return:从一个方法返回
跳出多重循环:在外面定义一个标识,然后使用带有标识的break
out:
for(int i = 0 ; i< 10 ; i++){
for(int j = 0 ; j < 10 ; j++){
if( j>3) break out;
}
}
3.3 final、finally 和finalize 的区别
final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可被继承。final 指的是引用的不可变性,
final StringBuffer s = new StringBuffer(“Hello“);
可以:s.append(“world”);
不可以:s = new StringBuffer(“Hello world”);
finally:作为处理异常的一部分,只能使用在try/catch 语句块中,并且附带一个语句块,表示这段语句最终一定会执行,经常用在需要释放资源的情况下。
finalize时Object 类的一个方法,在垃圾回收器执行时会调用被回收对象的finalize() 方法,可以覆盖此方法来实现对其他资源的回收。
3.4 assert 的作用
断言(assert) 主要对一个boolean 表达式进行检查,主要包括:检查流控制;检查输入是否有效;检查函数结果是否有效;检查程序不变量。在运行时开启。
3.5 static 关键字的作用
一、为某种特定的数据类型或者对象分配单一的存储空间,而与创建对象的个数无关;
二、实现某个方法或属性与类而不是与对象关联在一起,也就是说可以通过类来直接调用静态方法或者使用类的属性。
static很重要的一个用途时实现单例模式;
1) static 成员变量
2) static 成员方法:不能使用this,super 关键字,实现单例模式,为了实现这一功能,必须构建隐藏函数,即把构造函数声明为private,并提供一个创建对象的方法,该方法声明为static:
class Singleton{
private static Singleton instance = null;
privateSingleton(){}
public staticSingleton getInstance() {
if (instance== null) instance = new Singleton ();
}
}
3) static 代码块: JVM 在加载类的时候会执行static 代码块,经常用来初始化静态变量
4) static 内部类:只有内部类才能被定义为static
3.6 使用switch 注意事项
switch语句用于多分支选择,在使用switch(expr) 时,expr只能是一个枚举常量或者一个整数表达式,case 后跟 break,最后有default。
3.7 volatile 的作用
volatile是一个类型修饰符,被volatile 定义的变量,系统每次用到它时都会直接从对对应的内存当中提取,而不会利用缓存。
不具有原子性,不能替代synchronized。
3.8 instanceof 的作用
是二元运算符,作用是判断一个引用类型的变量所指向的对象是否是一个类的实例。
result= object instanceof class
if(string instanceof String) àresult= true
3.9 Strictfp 的作用
strictfp是 strict float point 的缩写, 可以保证浮点运算的精确性,而且在不同平台上有一致的运行结果。
public strictfp class Test {
publicstatic void main (String args []) {
floatf= 1.521131f;
doubled = 0.2163554d;
System.out.println(d+f);
}
}
四、基本类型与运算
4.1 Java提供的基本类型
int,short, long, byte, float, double, char, boolean
4.2 不可变类
4.3 值传递和引用传递的区别
(1) 值传递
在方法调用中,实参会把它的值传递给形参,形参只是用实参的值初始化一个存储单位,因此形参和实参虽有有着相同的值,但是却有着不同的存储单元,因此对形参的改变不会影响实参的值。
(2) 引用传递
在方法调用中,传递的是对象(也可以看作是传递的地址单位),这时形参和实参的对象都指向同一存储单元,因此对形参的修改也会影响实参的值。
在Java预言中,原始数据类型在传递参数时都是按值传递,而包装类型数据在传递数据时是按引用传递的。
4.4 不同参数类型转换的规则
低精度向高精度转换:byte < short < char <int < long < float < double
4.5 强制类型转换的注意事项
shorts = 1 ;
s = (short) (s +1);
OR s += 1;
4.6 运算符优先级
4.7 Math 中的round、ceil 和 floor 方法的功能
round: 四舍五入
ceil: 向上取整
floor:向下取整
4.8 i++ 和 ++i
i++先使用 i 后再自增 1
++i先自增1,再使用 i
i-- 和 --i 同理
4.9 实现无符号数的右移
>>:有符号的右移,负数高位补一,正数高位补零
>>>: 无符号的右移,高位补零
4.10 检查字符串中是否包含中字
String string;
if ( string.length () == string.getBytes().length)
五、字符串与数组
5.1 字符串创建与存储的机制
1)String s = new String(“abc”); 使用到 new 总会产生新的对象,也意味着新的存储地址
2)String s = “abc”;在JVM中存在着一个字符串池,有常量池
5.2 “==”、“equals”和 hashcode 的区别
1)“==”用来比较两个变量的值是否相等
2)equals 是Object 类提供的方法之一,比较的是引用,他的特殊之处在于可以被覆盖,
3)hashcode()方法是从object 类中继承过来的,用来鉴定两个对象是否相等。hashcode()方法返回对象再内存中地址转换成一个int 值,需要重写。
5.3 String、StringBuffer、StringBuilder和StringTokenizer的区别
String是不可变类,StringBuffer 是可变类,共享时用String,经常修改的字符串用StringBuffer,
Strings = “hello” OR new String(“hello”)
StringBuffers = new StringBuffer(“hello”)
StringBuilder也是可以被修改的字符串,与StringBuffer都是字符缓冲区的
StringBuffer是线程安全的,StringBuilder 不是线程安全的。
速率: StringBuilder > StringBuffer >String
单线程采用StringBuilder ,小数量采用String
StringTokenizer 是用来分割字符串的工具类。
5.4 Java中数组是不是对象
数组是对象,因为有他自己的一些特性。
5.5 数组的初始化方式
typearrayName [];
type[] arrayName;
5.6 length属性 和length()方法的区别
数组提供了length属性
字符串提供了length()方法
计算对象大小的方法 size(),主要针对泛型
六、异常处理
6.1 finally 块中的代码什么时候被执行
finally代码块的作用就是保证无论出现什么情况,finally的代码一定会执行,因此finally是在return之前执行的,如果finally代码块中有return,则会覆盖之前的return,转而执行finally代码块中的return。
遇到未到try块代码就停滞的时候,或者在try 块中出现exit()的时候,finally不会被执行。
6.2 异常处理的原理
异常处理是指程序运行(非编译)时发生非正常情况或者错误时,JVM 就会将错误表示为一个异常并抛出。
6.3 运行时的异常和普通异常的区别
Java提供两种错误的类:Error(程序直接终止),Exception(可以捕获)
Exception包含两种:检查异常和运行异常
检查异常(checked exception):IO异常,SQL异常,发生在编译阶段
运行异常(runtime exception):
NullPointException
ClassCastException
ArrayIndexOutOfBoundsException
ArrayStoreException
BufferOverflowException
ArithmeticException
1)Java在捕获异常时,先捕获子类,再捕获基类。
2)尽早抛出异常
3)可以自定义异常,但是得继承自Exception
4)异常能处理就处理,不能就抛出
七、输入输出流
7.1Java IO 流的实现机制是什么
流的本质是数据传输,分为字节流和字符流,主要区别是字节流在处理输入输出时不会用到缓存,字符流会用到缓存。
字节流(8bit):包含两个抽象类:InputStream(输入流)和OutputStream
字符流(16bit):包含两个抽象类:Reader 和 Writer
抽象装饰者。。。。。。
7.2 管理文件和目录的类
File的一些方法:
File (String Pathname), createNewFile (), delete (), isFile (), isDirectory (), listFiles (), mkdir (), exists ().
7.3 Java Socket
网络上的两个程序通过一个双向的通信实现数据的交换,这个双向链路的一端称为一个Socket。Socket 也称之为套接字,可以用来实现不同虚拟机或者不同计算机之间的通信。在Java中,Socket可以分为两种类型:面向连接的Socket通信协议(TCP, Transmission Control Protocol, 传输控制协议) 和面向无连接的Socket 通信(UDP,User Datagram Protocol, 用户数据报协议)。任何一个Socket都是由 IP地址和端口号唯一确定的。
基于TCP的通信过程:
- 首先,Sever 端的Listen (监听)指定的某个端口是否有连接请求,
- 其次,Client 端向Sever端发出Connect(连接)请求;
- 最后,Sever端向Client端发回Accept(接受)消息。
至此,一个连接就建立起来了。双方都可以通过Send, Write等方法与对方通信。
Socket的生命周期可以分为三个阶段:打开Socket,使用Socket收发数据,关闭Socket。在Java中,使用SeverSocket 作为服务器端,Socket作为客户端来实现通信。
7.4 java NIO
非阻塞(Nonblocking IO, NIO) 代替了Socket传统的通信模式。
NIO 通过Selector、Channel 和Buffer 来实现,主要采用了Reactor(反应器)的设计模式。
Channel 可以被看作一个双向通道,Selector实现了一个线程来管理多个通道。
7.5 Java 序列化
Java提供的两种对象持久化的方式,为序列化和外部序列化。
- 序列化(Serialization)
序列化是一种将对象以一串字符描述的过程,用于解决在对对象流进行读写操作时所引发的问题,序列化可以将对象的状态写在流流里进行网络传输,在需要时可以通过流里面信息重构一个一样的对象。
所有的序列化都必须实现Serializable接口,他不包含任何方法,使用一个输出流构造一个对象。
序列化的特点:
a: 如果一个类能够被序列化,那么他的子类也能够被序列化
b: static代表静态变量,是类的成员,transient 代表对象的临时数据,因此被声明为这两种类型的数据是不能被序列化的。
需要序列化的情况:
a: 需要通过网络来传输对象,或者对象的状态需要被永久的存储;
b: 序列化可以实现深复制,即可以复制引用的对象。
- 外部序列化
与序列化主要的区别在于是内置的API ,只需要实现Serialization接口,其余的需要开发者自己编写。
7.6 System.out.println()
System.out.println(1+2+” ”); 3
System.out.println( “ ”+ 1+2); 12
八、Java平台与内存管理
8.1 Java是平台独立语言
保证Java平台独立性的是“中间码”和“JVM”(Java virtual machine);
Java程序被编译后并不是直接生成能够在硬件平台上执行的代码,而是生成一个“中间码”。不同的平台装有不同的JVM,由JVM把“中间码”负责翻译成硬件能够执行的代码。
8.2 Java平台与其他平台的差别
8.3 JVM加载class文件的原理机制
类的加载:隐式加载:使用new()等方式创建一个类;显示加载:class.forName()
ClassLoader和他的子类实现类的加载
类在加载时可分为三类:基础类,扩展类和自定义类
步骤可分为三步:
- 装载。根据查找路径找到相对应的class文件并导入
- 链接:a:检查,检查待加载class文件的正确性
b:准备,给类中的静态变量分配存储空间
c:解析,将符号引用转变为直接引用
- 初始化。对静态变量和静态代码块执行初始化工作。
8.4 GC 垃圾回收机制(Garbage Collection,GC)
主要完成三项任务:
- 分配内存
- 确保被引用对象的内存不被错误的回收
- 回收不再被引用对象的内存空间
垃圾回收算法:
- 引用计数算法(Reference Counting Collector)
- 追踪回收算法(Tracing Collector)
- 压缩回收算法(Compacting Collector)
- 复制回收算法(Coping Collector)
- 按代回收算法(Generational Collector)
8.5 Java的内存泄漏问题
主要是有给对象赋予新值,重新分配了内存空间
引起内存泄漏的主要原因有:
- 静态集合类:生命周期和程序一样长
- 各种连接:数据库不显示的关闭
- 监听器:释放对象的同时没有删除监听器
- 变量不合理的作用域:变量定义的作用域大于其使用域
- 单例模式可能会造成内存泄漏
8.6 Java中堆和栈的区别
堆和栈都是存放数据的地方。变量分为基本数据类型和引用类型,基本数据类型的变量以及对象的引用变量,其内存都分配在栈上,变量出了作用域就会自动释放,而引用类型的变量,其内存往往分配在堆上或者常量池(例如字符串常量和基本数据类型常量),需要通过new() 等方式进行创建。
栈的内存主要用来存放基本数据类型与引用变量
堆的内存主要用来存放运行时创建的对象
九、容器
9.1 Java Collections 的框架
Java Collections框架中包含了大量集合接口以及实现这些接口的实现类和操作他们的的算法啊(排序,查找,反转,替换,复制,取极值等),主要有List(列表),Queue(队列),Set(集合),Stack(栈),Map(映射表)。其中List,Queue,Set,Stack都继承自Collection接口。
- Set 里面的元素不可重复,HashSet,TreeSet实现了Set接口
- List里面的元素存储有序,LinkedList,ArrayList,Vector实现了List接口
- Map提供了键值一一映射关系,HashMap,TreeMap,LinkedHashMap,
9.2 迭代器
迭代器(Iterator)是一个对象,他可以遍历并选择序列中的对象,它提供了一种访问一个容器(container)对象中的各个元素而又不比显示细节的方法。
注意事项:
- 使用容器的iterator()方法返回一个Iterator,然后通过Iterator的next()方法访问返回的第一个元素
- 使用Iterator的hasNext()方法判断容器是否还有元素
- remove() 方法删除迭代器返回的元素
9.3 ArrayList、Vector和LinkedList
ArrayList和Vector都是开辟一个连续的存储空间,插入效率不高,当元素超过时,会动态的增加原来的1.5倍和2倍(可以改变)的存储单元,ArrayList没有同步的方法,Vector的绝大多数方法都是直接或者间接同步的,因此ArrayList不是线程安全的,Vector是线程安全的,性能上不如ArrayList。
LinkedList采用双向列表实现,访问效率底下,但是插入效率很好。
9.4 HashTable,HashMap,TreeMap和WeakHashMap
HashMap 和 HashTable
- HashMap是HashTable的轻量级实现(非线程安全的实现),允许一条null值
- HashMap去掉了HashTable的contains方法,改为containsvalue和containsKey,
- HashTable是线程安全的,而HashMap不支持线程同步,
- HashTable 使用Enumeration, HashMap使用Iterator
- 采用的hash/rehash算法几乎一样,效率差不多
- HashTable 的hash是11,增加是old x 2 + 1 ,HashMap的hash默认是16,增加为2的指数
- hash值使用的不同,HashTable直接使用对象的hashcode。
9.5 自定义的HashMap 和HashTable的key需要注意
键不能够重复
需要注意事项:
1)如需要根据对象的相关属性来自定义对象是否相等,需要重写equals(),一旦重写了equals(),就必须要重写hasCode()方法;
- 当自定义类的多项作为HashMap(HashTable)的key值时,最好把这个类设计为不可变类;
- 如果两个key相等,则有相同的hashCode,反之不成立
9.6 Collection 和Collections
Collection是一个集合接口
Collections是针对集合类的一个包装类,提供了一系列静态方法以实现对各种集合的搜索,排序,线程安全等操作。
十、多线程
10.1 线程,进程
线程是指程序在执行过程中,能够执行程序代码的一个执行单元,有四种状态:运行,就绪,挂起,结束
进程是指一段正在执行的程序,一个进程可以拥有多个线程,各个线程之间共享程序的内存空间,但是各个线程拥有自己的栈空间,
在操作系统级别上,程序的执行都是以进程为单位的
多线程的优点:
- 使用多线程可以减少程序的响应时间
- 与进程相比,线程的创建和切换开销比较小
- 多线程可以更好的利用多核CPU,资源利用充分
- 使用多线程能简化程序的结构,使程序便于理解和维护
10.2 同步和异步
多线程里面数据共享的问题
要实现同步,必须获得每一个线程对象的锁,获得锁可以保证在一个时刻只有一个线程可以进入临界区,并且在该锁释放之前,其他线程不能进入临界区,当其他线程想要获得该对象的锁,只能进入等候队列,只有拥有该对象锁的线程退出临界区时,锁才会被释放,等待队列中优先级最高的线程才能够获得该对象锁,进入数据临界区
实现同步的方式:1)利用同步代码块;2)利用同步方法
关键字synchronized实现同步,开销太大,有可能造成死锁
异步与非阻塞相似,不比关心其他线程的状态或者行为
10.3 实现Java多线程
实现的三种方法:
1)继承Thread类,重写run()方法
class MyThread extends Thread{
public void run(){
System.ouot.println(“Thread body”);//线程的内容
}
}
public class Test{
public static void main(String[] args){
MyThread mythread = new MyThread();
mythread.start();//开启线程
}
}
2)实现Runnable接口,并实现该接口的run()方法
a: 自定义类并实现Runnbale接口,实现run()方法
b: 创建Thread对象爱那个,用实现Runnable接口的对象作为参数实例化该Thread 对象
c: 调用Thread 的start() 方法
class MyThrad implememnts Runnable{
public void run(){
System.out.println(“Thread body”);
}
}
public class Test{
public static void main(String[] args){
MyThread thread = new MyThread();
Thread t = new Thread(thread);
t.start();
}
}
3)实现Callable接口,重写call()方法
能够返回值,主要的特点
a: Callable 可以在任务结束后提供一个返回值,Runnable 无法提供这个功能
b: Callable 中的call() 方法可以抛出异常,Runnable不能够抛出异常
c: 运行Callable可以拿到一个Future对象,表示一步计算结果
public class CallableAndFuture{
public static class CallableTest implements Callable<String>{
public String call() throws Exception{
return “Hello World”;
}
}
}
public static void main(String[] args){
ExecutorService threadPool = Executors.newSingleThreadExecutor();
//启动线程
Future<String> future = threadPool.submit(new CallableTest());
try{
System.out.println(“wating thread to finish”);
System.out.println(future.get());
}catch(Exception e){
e.printStackTrace():
}
}
10.4 run() 方法与start() 方法
start()方法可以异步的调用一个线程,但是run() 方法是同步的调用函数,
在一个线程中使用start() 方法时,可以启动另外一个已经准备就绪的线程,但是使用run() 方法时,相当于调用了一个函数,不会启动别的线程。
E:\Java_Code\src\ThinkingInJava\TestThreads.java
10.5 多线程同步的方法
三种同步机制:
1)synchronized 关键字
每个对象都有一个对象锁与之关联,该锁表明对象在任意时刻只允许被一个线程所拥有,当一个线程调用对象的一段synchronized代码时,需要先获得该对象的锁,然后执行相应的代码,结束后释放锁。
synchronized有两种用法,还可以作用于静态方法,类或者某个实例
a: synchronized方法。在方法的申明前加入synchronized关键字
public synchronized void mutiThreadAccess();
b: synchronized块。
synchronized( syncObject){
//访问syncObject 的代码
}
2)wait() 方法与 notify()方法
在synchronized 代码块被执行时,对象的wait() 方法可以释放对象锁,notify()可以唤醒等待队列中的第一个线程并允许该线程去获取对象锁,notifyAll() 方法可以唤醒所有等待队列中的线程,并让他们去竞争该对象的锁。
3)Lock
Lock接口,实现类ReentrantLock
实现方法:
a: lock(),以阻塞的方法获取锁,,获取到锁,立即返回,该对象正在被其他线程持有锁,等待获取到后返回。
b: tryLock()。以非阻塞的方式获取锁,尝试性的方式获取锁,如果获取到,立刻返回true,否则,立刻返回false
c: tryLock(long tirmout, TimeUnit unit)。
d: lockInterruptibly()。
10.6 sleep() 和wait()
区别主要有:
1)原理不同。sleep() 方法是线程Thread的静态方法,是线程用来控制自身流程的,他会使自身暂停一段时间,而把执行机会让给其他线程,等到计时时间一到,就会苏醒;wait() 方法是Object类的方法,用于线程间通信,调用该方法会使拥有该对象锁的进程进入等待状态,直到其他线程调用notify方法(notifyAll),或者开发人员自定义时间。
2)对锁的处理机制不同
sleep()不会释放锁,而wait方法会使得线程释放掉他所占用的锁
3)使用区域不同
wait() 必须放在同步方法或者同步语句块中,而sleep可以放在线程的任意地方
10.7 终止线程的方法
stop() 方法会直接关闭当前线程并且释放所有的监视资源,但是会造成线程运行时调用资源的不一致;
suspend() 方法会挂起当前线程,并不释放资源,会造成死锁,譬如该挂起的线程中有对象锁,被挂起,但是其他的线程正在等待该线程运行结束释放对象锁。
一般建议等待程序自己运行结束进入dead状态。设置volatile的标识
使用interrupt()方法,InterruptedException
10.8 synchronized 与Lock
synchronized 使用Object对象本身的wait,notify,notifyAll调度机制,而Lock 可以使用Condition进行线程之间的调度,完成synchronized实现的所有功能。
区别:
1)用法不一样
synchronized既可以加在方法上,也可以加在代码块上,括号中表示需要锁的对象
Lock需要显示地指定起始位置和终止位置
2)性能不一样
3)锁机制不一样
10.9 线程守护
用户线程和守护线程,守护线程优先级比较低,需要在启动线程之前调用对象的setDemo(ture)方法。
10.10 join()方法
join()方法的作用就是让调用该方法的线程在执行完run() 方法后,再执行join方法后面的代码,就是将两个线程合并,实现同步功能。
十一、Java数据库
11.1 通过JDBC访问数据库
步骤:
- 加载JDBC驱动器。
- 加载JDBC驱动。
- 建立数据库连接,取得Connection对象。
- 建立Statement对象或者PreparedStatement对象
- 执行SQL语句。
- 访问结果集ResultSet对象。
- 依次将ResultSet、Statement、Connection对象关闭,释放所占资源。
11.2 JDBC处理事务采用的方法
commit()
rollback()
JDBC 的事务隔离级别
- transaction_none jdb.不支持事务
- transaction_read_uncommitted。未提交读
- transaction_read_committed。已提交读
- transaction_repeatable_read。可重复读
- transaction_serializable。可序列化
11.3 Class.forName 的作用
任何类只有装载到JVM上才可以运行。Class.forName方法的作用就是把类加载到JVM中。
11.4 Statement、PreparedStatement 、CallableStatement
statement 用于执行不带参数的简单SQL语句
PreparedStatement表示预编译的SQL语句,用于执行带参数的预编译SQL语句
CallableStatement 提供了用来调用数据库中存储过程中的接口。
PreparedStatement相比Statement的优点:
- 效率更高
- 代码可读性和可维护性更好
- 安全性更好
CallableStatement 调用已存储过程的方法
11.5 getString() 方法和getObject()方法
查询数据量过大时,使用getObject()方法
JDO(Java Data Object)——Java数据库对象,时用于存取某种数据仓库中的对象的标准化API。
11.6 JDBC 与Hibernate的区别
Hibernate是JDBC的封装,采用配置文件的形式将数据库的连接参数写到XML文件中,Hibernate是一个持久层框架。