随堂复习(异常处理、多线程)

第09章:随堂复习(异常处理)


一、随堂复习

1. 异常的概述

1. 什么是异常?
指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。

2. 异常的抛出机制
Java中把不同的异常用不同的类表示,一旦发生某种异常,就`创建该异常类型的对象`,并且抛出(throw)。
然后程序员可以捕获(catch)到这个异常对象,并处理;如果没有捕获(catch)这个异常对象,那么这个异常
对象将会导致程序终止。

3. 如何对待异常
 对于程序出现的异常,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是程序员在编写程序时,
 就充分考虑到各种可能发生的异常和错误,极力预防和避免。实在无法避免的,要编写相应的代码进行异常的检测、
 以及`异常的处理`,保证代码的`健壮性`。

2. 异常的体系结构及常见的异常

java.lang.Throwable:异常体系的根父类
    |---java.lang.Error:错误。Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。
                         一般不编写针对性的代码进行处理。
               |---- StackOverflowError、OutOfMemoryError

    |---java.lang.Exception:异常。我们可以编写针对性的代码进行处理。
               |----编译时异常:(受检异常)在执行javac.exe命令时,出现的异常。
                    |----- ClassNotFoundException
                    |----- FileNotFoundException
                    |----- IOException
               |----运行时异常:(非受检异常)在执行java.exe命令时,出现的异常。
                    |---- ArrayIndexOutOfBoundsException
                    |---- NullPointerException
                    |---- ClassCastException
                    |---- NumberFormatException
                    |---- InputMismatchException
                    |---- ArithmeticException

【面试题】说说你在开发中常见的异常都有哪些?

开发1-2年:
|----编译时异常:(受检异常)在执行javac.exe命令时,出现的异常。
    |----- ClassNotFoundException
    |----- FileNotFoundException
    |----- IOException
|----运行时异常:(非受检异常)在执行java.exe命令时,出现的异常。
    |---- ArrayIndexOutOfBoundsException
    |---- NullPointerException
    |---- ClassCastException
    |---- NumberFormatException
    |---- InputMismatchException
    |---- ArithmeticException

开发3年以上:
OOM。

3. 异常处理的方式

过程1:"抛"
 >"自动抛" : 程序在执行的过程当中,一旦出现异常,就会在出现异常的代码处,自动生成对应异常类的对象,并将此对象抛出。

 >"手动抛" :程序在执行的过程当中,不满足指定条件的情况下,我们主动的使用"throw + 异常类的对象"方式抛出异常对象。


过程2:"抓"
    狭义上讲:try-catch的方式捕获异常,并处理。
    广义上讲:把"抓"理解为"处理"。则此时对应着异常处理的两种方式:① try-catch-finally ② throws
3.1 try-catch-finally
1. 基本结构:
try{
   ...... //可能产生异常的代码
}
catch( 异常类型1 e ){
   ...... //当产生异常类型1型异常时的处置措施
}
catch( 异常类型2 e ){
   ......     //当产生异常类型2型异常时的处置措施
}
finally{
   ...... //无论是否发生异常,都无条件执行的语句
}

2. 使用细节:
> 将可能出现异常的代码声明在try语句中。一旦代码出现异常,就会自动生成一个对应异常类的对象。并将此对象抛出。
> 针对于try中抛出的异常类的对象,使用之后的catch语句进行匹配。一旦匹配上,就进入catch语句块进行处理。
  一旦处理接触,代码就可继续向下执行。
> 如果声明了多个catch结构,不同的异常类型在不存在子父类关系的情况下,谁声明在上面,谁声明在下面都可以。
  如果多个异常类型满足子父类的关系,则必须将子类声明在父类结构的上面。否则,报错。
> catch中异常处理的方式:
   ① 自己编写输出的语句。
   ② printStackTrace():打印异常的详细信息。 (推荐)
   ③ getMessage():获取发生异常的原因。
> try中声明的变量,出了try结构之后,就不可以进行调用了。
> try-catch结构是可以嵌套使用的。

3. finally的使用说明:
3.1 finally的理解
> 我们将一定要被执行的代码声明在finally结构中。
> 更深刻的理解:无论try中或catch中是否存在仍未被处理的异常,无论try中或catch中是否存在return语句等,finally
  中声明的语句都一定要被执行。

> finally语句和catch语句是可选的,但finally不能单独使用。

3.2 什么样的代码我们一定要声明在finally中呢?
> 我们在开发中,有一些资源(比如:输入流、输出流,数据库连接、Socket连接等资源),在使用完以后,必须显式的进行
关闭操作,否则,GC不会自动的回收这些资源。进而导致内存的泄漏。
  为了保证这些资源在使用完以后,不管是否出现了未被处理的异常的情况下,这些资源能被关闭。我们必须将这些操作声明
在finally中!
3.2 throws
1. 格式:在方法的声明除,使用"throws 异常类型1,异常类型2,..."

2. 举例:

public void test() throws 异常类型1,异常类型2,.. {
    //可能存在编译时异常
}


3. 是否真正处理了异常?
> 从编译是否能通过的角度看,看成是给出了异常万一要是出现时候的解决方案。此方案就是,继续向上抛出(throws)。
> 但是,此throws的方式,仅是将可能出现的异常抛给了此方法的调用者。此调用者仍然需要考虑如何处理相关异常。
  从这个角度来看,throws的方式不算是真正意义上处理了异常。


4. 方法的重写的要求:(针对于编译时异常来说的)
子类重写的方法抛出的异常类型可以与父类被重写的方法抛出的异常类型相同,或是父类被重写的方法抛出的异常类型的子类。

开发中的经验之谈:

开发中,如何选择异常处理的两种方式?(重要、经验之谈)
- 如果程序代码中,涉及到资源的调用(流、数据库连接、网络连接等),则必须考虑使用try-catch-finally来处理,
  保证不出现内存泄漏。
- 如果父类被重写的方法没有throws异常类型,则子类重写的方法中如果出现异常,只能考虑使用try-catch-finally
  进行处理,不能throws。
- 开发中,方法a中依次调用了方法b,c,d等方法,方法b,c,d之间是递进关系。此时,如果方法b,c,d中有异常,
  我们通常选择使用throws,而方法a中通常选择使用try-catch-finally。

4. 手动throw异常对象

在方法内部,满足指定条件的情况下,使用"throw 异常类的对象"的方式抛出。

5. 如何自定义异常类

① 继承于现有的异常体系。通常继承于RuntimeException \ Exception
② 通常提供几个重载的构造器
③ 提供一个全局常量,声明为:static final long serialVersionUID;

为什么需要自定义异常类?
我们其实更关心的是,通过异常的名称就能直接判断此异常出现的原因。既然如此,我们就有必要在实际开发场景中,
不满足我们指定的条件时,指明我们自己特有的异常类。通过此异常类的名称,就能判断出具体出现的问题。

第10章:随堂复习与企业真题(多线程)


一、随堂复习

1. 几个概念

程序(program):为完成特定任务,用某种语言编写的`一组指令的集合`。即指一段静态的代码。

进程(process):程序的一次执行过程,或是正在内存中运行的应用程序。程序是静态的,进程是动态的。
              进程作为操作系统调度和分配资源的最小单位。

线程(thread):进程可进一步细化为线程,是程序内部的一条执行路径。
             线程作为CPU调度和执行的最小单位

线程调度策略
分时调度:所有线程`轮流使用` CPU 的使用权,并且平均分配每个线程占用 CPU 的时间。

抢占式调度:让`优先级高`的线程以`较大的概率`优先使用 CPU。如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

> 单核CPU与多核CPU
> 并行与并发

2. 如何创建多线程(重点)

  • 方式1:继承Thread类
  • 方式2:实现Runnable接口
  • 方式3:实现Callable接口 (jdk5.0新增)
  • 方式4:使用线程池(jdk5.0新增)

3. Thread类的常用方法、线程的生命周期

熟悉常用的构造器和方法:
1. 线程中的构造器
- public Thread() :分配一个新的线程对象。
- public Thread(String name) :分配一个指定名字的新的线程对象。
- public Thread(Runnable target) :指定创建线程的目标对象,它实现了Runnable接口中的run方法
- public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

2.线程中的常用方法:
> start():①启动线程 ②调用线程的run()
> run():将线程要执行的操作,声明在run()中。
> currentThread():获取当前执行代码对应的线程
> getName(): 获取线程名
> setName(): 设置线程名
> sleep(long millis):静态方法,调用时,可以使得当前线程睡眠指定的毫秒数
> yield():静态方法,一旦执行此方法,就释放CPU的执行权
> join(): 在线程a中通过线程b调用join(),意味着线程a进入阻塞状态,直到线程b执行结束,线程a才结束阻塞状态,继续执行。
> isAlive():判断当前线程是否存活

3. 线程的优先级:
getPriority():获取线程的优先级
setPriority():设置线程的优先级。范围[1,10]


Thread类内部声明的三个常量:
- MAX_PRIORITY(10):最高优先级
- MIN _PRIORITY (1):最低优先级
- NORM_PRIORITY (5):普通优先级,默认情况下main线程具有普通优先级。

线程的生命周期:

jdk5.0之前:

jdk5.0及之后:Thread类中定义了一个内部类State

java 复制代码
public enum State {
        
        NEW,
    
        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,
 
        TERMINATED;
}

4. 如何解决线程安全问题(重点、难点)

  • 什么是线程的安全问题?多个线程操作共享数据,就有可能出现安全问题。

  • 如何解决线程的安全问题?有几种方式?

    • 同步机制:① 同步代码块 ② 同步方法

      • 重点关注两个事:共享数据及操作共享数据的代码;同步监视器(保证唯一性)

        在实现Runnable接口的方式中,同步监视器可以考虑使用:this。
        在继承Thread类的方式中,同步监视器要慎用this,可以考虑使用:当前类.class。

        非静态的同步方法,默认同步监视器是this
        静态的同步方法,默认同步监视器是当前类本身。

    • jdk5.0新增:Lock接口及其实现类。(保证多个线程共用同一个Lock的实例)

5. 同步机制相关的问题

  • 懒汉式的线程安全的写法
  • 同步机制会带来的问题:死锁
    • 死锁产生的条件及规避方式

6. 线程间的通信

  • 在同步机制下,考虑线程间的通信

  • wait() 、notify() 、notifyAll() 都需要使用在同步代码块或同步方法中。

  • 高频笔试题:wait() / sleep()

相关推荐
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
java·开发语言·unity·c#·游戏引擎·里氏替换原则
@菜鸟进阶记@1 小时前
java根据Word模板实现动态填充导出
java·开发语言
卖芒果的潇洒农民1 小时前
Lecture 6 Isolation & System Call Entry
java·开发语言
SomeB1oody1 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust
Kisorge2 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
轻口味3 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学4 小时前
QT-简单视觉框架代码
开发语言·qt
威桑4 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服4 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt