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( )方法的时候,会放弃对象锁定)

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐