21天学通Java学习笔记-Day07(异常-断言-线程)
Day07:异常:运行期间出现的错误。异常是对象,从Throwable 派生出来,Throwable 下的异常都可以抛出。 Throwable 有两个子类:Error(错误) 和 Exception(异常)。Error 是java运行环境(虚拟机)内部出错,不可处理。Exception 可以处理的异常,这个必须捕捉,可以处理。 Exception 分两种子类:RuntimeEx
Day07:
异常:运行期间出现的错误。异常是对象,从Throwable 派生出来,Throwable 下的异常都可以抛出。
Throwable 有两个子类:Error(错误) 和 Exception(异常)。Error 是java运行环境(虚拟机)内部出错,不可处理。Exception 可以处理的异常,这个必须捕捉,可以处理。
Exception 分两种子类:RuntimeException(运行时出的错误,也是经常发生的错误,可以catch可以不catch)和 其它错误(必须catch)。
捕捉,处理异常的方法:
try(捕捉) {
会出异常的语句;
} catch(处理)(一个异常类型) {
处理语句;
}
try {
会出异常的语句;
} catch (IOException e) {
处理语句;
}
finally语句:finally 里的语句一定会被执行,多用于异常发生后的强制退出,释放外部资源,关闭打开文件等。
try {
会出异常的语句;
} catch (IOException e) {
处理语句;
}
finally{
强制执行语句;
}
finally 除了御用处理异常外还有其他用途:在循环中,可在语句 return , break 或者 continue 后面使用它来执行清理代码,在这种情况下,可使用包含 finally 语句但不包含 catch 语句的 try 语句。
抛出异常的方法:
使用关键字 throws ,抛出方法可能会出现的异常,但是不对异常进行处理(异常向上传递,最后可以自己捕捉,也可以交给java自己处理)。
格式:
方法名(参数)throws 异常类型1,异常类型2...... {
}
抛出多个异常,每个异常之间用(,)隔开。
关键字 throw 对异常实例的处理。发生异常,方法运行到 throw 后会终止,下面的语句不会执行到。
throw 可以放在catch { }中,用于引发异常后的退出。
a( ) throws IOException {
throw IOException("NO!");
}
或者
a( ) throws IOException {
IOException e = new IOException("NO!");
throw e;
}
异常类都会存在一个带 String 参数的构造方法;
异常的传递:
当一个方法抛出一个异常,另一个方法调用该方法不想处理这个异常可以继续抛出这个异常............直到 main 方法调用该方法时,可以选择处理也可以交给java自己处理。
a( ) throws IOException {
}
b( ) throws IOException { b方法调用a方法,不处理a的异常,继续抛出
a( );
}
c( ) throws IOException { c方法调用b方法,不处理b异常,继续抛出
b( );
}
..................
public static void main(String[] args) { 到了main方法可以选择继续 throws 异常交给java处理,也可以自己try{ }catch{ }处理这个异常
}
断言: 关键字 assert 加上逻辑语句。
检查一个方法的值是否正确:
class test {
public static void main(String[] args) {
test t = new test01();
t.a(4);
}
void a(int i){
assert i>6:"NOT"; //用断言判断参数,如果true正常执行下面语句,如果false打印出NOT
System.out.println(i);
}
}
检测类变量是否正确:
class test {
static int a;
public static void main(String[] args) {
a=3;
assert a==4:"NOT 4"; //用断言判断参数,如果true正常执行下面语句,如果false打印出NOT
System.out.println(a);
}
}
assert 后面的逻辑表达式 (>,<,==,!=,三目运算 等)
java 中的断言是默认关闭,要等java文件编译后,使用 java -ea 文件名 命令打开。
线程:
线程在程序的其它代码执行其它工作时独立运行。也被称为多任务,因为程序可以同时处理多个任务。
线程的用途之一是将所有耗时的行为放进一个类中。
线程创建的方式有两种:1.从 Thread 类中派生(继承)然后重写 run( ) 方法,2. 实现 Runable 接口然后重写 run( ) 方法。
Runable 接口只有一个 run( ) 方法
启动线程用 Thread 类中的 start( ) 方法。
尽量用接口。
run 方法相当于新线程的 main 方法,是新线程的主方法。
线程的生命周期:新建(New)=》就绪(Runnable)=》运行(Running)=》阻塞(Blocked)=》死亡(Dead)
当 new 出 Thread 对象时线程被创建,当线程对象调用 statr( ) 方法后,线程就绪等待java虚拟机里线程调度后启动,当线程获得CPU后开始执行 run( ) 方法内容,这样线程处于运行状态
sleep(long o); sleep 方法是 Thread 类中的方法:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)会抛出 InterruptedException 异常
sleep 方法:暂停某一个线程。在哪个线程中调用 sleep();方法,哪个线程休眠。
interrupt(); interrupt 方法时 Thread 类中的方法:中断线程。如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。
join( );join方法是Thread 类中的方法:等待该线程终止(合并线程)。会抛出 InterruptedException 异常
join(long lo); Thread 类中的方法:等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。会抛出 InterruptedException 异常
join 方法:合并某一个线程。
yield( );yield方法是 Thread 类中的方法:暂停当前正在执行的线程对象,并执行其他线程。
yield 方法:让出CPU,给其它线程执行的机会。
currentThread(); currentThread方法是Thread类中的方法:返回当前正在执行的线程对象的引用。(拿到当前线程)
isAlive(); isAlive方法是Thread类中的方法:测试线程是否处于活动状态。线程活动返回 true ; 否则返回false
线程的优先级:Thread 类里面定义了三个静态常量:Thread.MAX_PRIORITY 值为10;Thread.MIN_PRIORITY 值为1;Thread.NORM_PRIORITY 是默认值5
可以通过对静态常量的加减设置优先级
用 Thread 类中的 setPriority(优先级静态常量) 来设置线程的优先级
用 Thread 类中的 getPriority( ) 返回指定线程的优先级
停止线程的方法:
正常停止线程的方法,设置一个 boolean 值为 true ,写一个线程结束的方法,在方法中将 boolean 值设成 false
锁定当前对象(也被称为 线程同步):关键字 synchronized
使用方法1:synchronized(obj){ } 参数 obj 是指定锁定的对象,锁定当前对象,不被其它对象打断。(也被称为 同步代码块)
使用方法2:public synchronized void XXX( ) { } 在执行 XXX 方法的时候将当前对象锁定。(也被称为 同步方法)
这种锁叫做:互斥锁
synchronized 锁定某一段代码,当执行到这段代码时,锁定当前对象,其他线程访问这个对象时,必须等待synchronized 代码执行完毕锁打开后,才能访问对象,执行代码
用关键字 synchronized 修饰的时候,该对象在任何时刻都只能有一条线程访问。
死锁:锁定对象A里包含锁定对象B(拿到B锁,A锁解开),锁定对象B包含锁定A的对象(拿到A锁,B锁就可以解开),互相拿不到可以解开的锁 就形成 死锁
死锁 例子代码:
public class TestDeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object(); //创建两个对象
public void run() {
System.out.println("flag=" + flag);
if(flag == 1) {
synchronized(o1) { //锁定o1对象
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o2) { //锁定o2对象后,程序才能继续执行
System.out.println("1");
}
}
}
if(flag == 0) {
synchronized(o2) { //锁定o2对象
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized(o1) { //锁定o1对象后,程序才能继续执行
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
TestDeadLock td1 = new TestDeadLock();
TestDeadLock td2 = new TestDeadLock();
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start();
}
}
关于 synchronized 的面试题:
看如下代码,tc.tii( );打印出来的值是多少?
class testcy implements Runnable{
int i = 10;
public synchronized void ti()throws Exception {
i = 100;
Thread.sleep(5000);
System.out.println("i"+i);
}
public void tii(){
System.out.println(i);
}
public void run () {
try{
ti();
}catch (Exception e){}
}
public static void main(String[] args) throws Exception {
testcy tc = new testcy();
Thread t = new Thread(tc);
t.start(); //调用run 方法中的ti()方法,tc对象的i值改变
/* 拥有tc对象的t对象锁定ti()方法的时候已经改变i值,
tc对象调用没有被锁定的tii()方法时i值已经被改变
*/
Thread.sleep(1000);
tc.tii (); //tc对象调用tii()方法,i值已经被ti()方法改变
}
}
互斥锁,保证任何时间只有一条线程访问锁定(同步)方法(块),不保证其它线程访问其它不锁定(同步)的方法。
线程暂停的第二种方法:wait( );
wait( );方法是 超级父类 Object 类的方法,所以任何对象都可以调用。wait( )方法:在其他线程调用此对象的 notify( ) 方法或 notifyAll( ) 方法前,导致当前线程等待。(当前线程必须锁定(同步,也就是方法被 synchronized 修饰 )才可以使用 wait( )方法) 会抛出 InterruptedException 异常
唤醒线程的方法:notify( );
notify( );方法是超级父类 Object 类的方法,所有对象都可以调用,一般 notify( ) 和 wait( ) 方法一一对应。notify( )方法:唤醒一个正wait( )在这个对象上的线程(唤醒在这个锁定对象上等待的一个线程)。会抛出 IllegalMonitorStateException 异常
唤醒线程的方法二:notifyAll( );
notifyAll( );方法是超级父类 Object 类的方法,所有对象都可以调用。notifyAll( )方法:唤醒多个wait( )在这个对象上的线程(唤醒在这个锁定对象上等待的多个线程)。会抛出 IllegalMonitorStateException 异常
面试题:
wait( ) 和 sleep( ) 的区别?
wait( )方法是Object类的方法,而sleep( )是Thread类的方法
sleep( )方法在线程挂起时不释放同步锁(仍然持有对象锁定)
wait( )方法在线程挂起时释放同步锁 (调用wait( )方法的时候,会放弃对象锁定)
更多推荐
所有评论(0)