异常类&线程总结

发布时间 2023-12-28 20:48:43作者: ZWJAS

总结

异常

异常:就是Java中程序的一种错误

Java中异常机制:
表示程序的某个错误,当错误发生的时候,将程序结束,提示在那个位置出现什么错误

Java中异常的体系结构:每种错误就是一个类
Throwable类:java中错误、异常的父类
Error:错误,不能用Java代码处理错误

​ eg:
​ VirtualMachineError:虚拟机损坏的错误
​ StackOverflowError:堆栈溢出

Exception:异常,需要使用Java代码处理错误

​ 1. 编译时异常:编译之前必须处理的异常,强制处理的异常

​ 2. 运行时异常:不强制处理的异常

常见的异常

  1. 运行时异常
    NullPointerException:空指针异常(对象在堆里面没有引用,就直接调用方法)
    对象在调用方法或属性的时候需要做非空判断
    StringIndexOutOfBoundsException:字符串下标越界的异常
    只要操作数组下标,必须要做合法性判断
    ArrayIndexOutOfBoundsException:数组下标越界
    操作数组先做非空和空数组
    ArithmeticException:算术异常
    NumberFormatException:数值的格式异常
    ClassCastException:类型转化异常,对象向下转型的时候
  2. 编译时异常
    ParseException:转换日期格式的异常

区分编译时异常和运行时异常:
只要异常的父类时RuntimeException就是运行时异常,其他就是编译时异常

异常的处理方式:

  1. 甩锅式 在方法上抛出异常或者在方法里直接抛出
    throws在方法的声明上面抛出异常
    只要程序出现抛出的异常,JVM会创建相应对象,再去调用相应的方法来提示错误
    在方法体内抛出异常,throw 异常对象

    public class ExceptionDemo3 {
        // 声明一个方法
        public static void m() throws ParseException {  // 抛出异常,异常抛给调用者,thorws
            // 省略方法体
            new SimpleDateFormat("yyyy-MM-dd").parse("2023/12/19");
        }
       
        public static void mm() throws IOException {
        }
        
        public static void main(String[] args) throws ParseException   { // 直接抛给JVM
            m();
            mm();
    
            String str = "";
            str.length();
        }
    }
    
  2. 背锅式
    try{
    可能会出现异常的代码
    }catch(异常类名 参数名) {
    报这种异常错误信息的代码
    }.....注意:catch的顺序时先子后父
    finally {
    处理异常的出口
    作用:关闭资源
    }

    public class ExceptionDemo4 {
        public static void main(String[] args) throws ParseException {
            try {
               new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2023-12-19 14:11:20");
                return; // 结束方法
                System.exit(0);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            } finally {
                System.out.println("异常处理的出口");
            }
    
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2023-12-19 14:11:20");
    
        }
    }
    

    自定义异常

    ​ 写程序执行过程有不满条件情况都是异常,需要自己定义
    ​ class 自定义异常的名字(XxxException) extends Exception {
    ​ // 自定义编译时异常
    ​ 书写两个构造方法
    ​ 一个无参
    ​ 一个有1个字符串参数的构造方法
    ​ }
    ​ class 自定义异常的名字(XxxException) extends RuntimeException {
    ​ // 自定义运行时异常
    ​ }

    public class AccountStartWithCharException extends RuntimeException {
        public AccountStartWithCharException() {
        }
    
        public AccountStartWithCharException(String message) {
            super(message);
        }
    }
    
    /**
     * 自定义的异常:账号不在6-18位就会报这个异常
     */
    public class AccountSizeException extends Exception {
        public AccountSizeException() {
        }
    
        public AccountSizeException(String message) {
            super(message);
        }
    }
    

线程

  1. 进程:一个应用软件就是一个进程,一大段程序(代码)
    每一个进行运行都有独立内存空间
    优酷:进程A
    腾讯:进程B
    快播:进程C
    进程的运行相互不干扰

  2. 线程:一个进程里面独立某个功能就是一个线程,一小段代码
    其实软件运行的就是线程
    一个进程里面至少有一个线程,也可以有多个线程
    线程的运行也是独立,每个线程也有独立运行内存,这个内存时进程的内存

  3. 线程时怎样执行?
    1)、启动线程
    2)、线程就是待运行状态
    3)、cpu会统计目前内存中有多少个待运行的线程
    会将运行时间平均分配给每个待运行的线程
    4)、那个线程获得这个时间片,那这个线程就开始执行,直到时间片用完,线程就暂停
    注意:在cpu里面同一时间只能运行一个线程

  4. 为什么软件要设计位多线程?

    Java实现多线程的方式

    1)、继承Thread类,重写run()
    使用多线程

    public class Play extends Thread{ // Play是多线程
        // 重写run():线程获得时间片后执行的代码
    
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 获取当前线程的名字
                String name = Thread.currentThread().getName();
                System.out.println(name + ":播放视频第" + i + "次");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    
    /**
     * 多线程的测试类
     */
    public class PlayTest {
        public static void main(String[] args) {
            // 1、创建线程
            Play p1 = new Play(); // 开启一个线程 Thread-0
            Play p2 = new Play(); // 开启一个线程 Thread-1
            Play p3 = new Play(); // 开启一个线程 Thread-2
            // 2、开启线程,start()
    //        p1.start(); // 启动p1线程
    //        p2.start();
    //        p3.start();
            p1.setDaemon(true);
            p1.setName("蘋蘋");
            System.out.println(p1.isDaemon());
    //        p1.setPriority(10);
    //        System.out.println(p1.getPriority());
    
        }
    }
    

    2)、实现Runnable接口,重写run()

    /**
     * 实现Runnable接口,来实现多线程
     */
    public class Down implements Runnable{
        @Override
        public void run() {
            for (int i = 1; i <= 10 ; i++) {
                System.out.println("下载视频第" + i + "次");
            }
        }
    }
    
    /**
     * 实现接口创建多线程的测试类
     */
    public class DownTest {
        public static void main(String[] args) {
            // 1、创建Runnable对象
            Down d1 = new Down();
            // 2、创建线程对象
            Thread t1 = new Thread(d1); // 创建第一个线程
            Thread t2 = new Thread(d1); // 创建第一个线程
            Thread t3 = new Thread(d1); // 创建第一个线程
            // 3、启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

    讲解Thread类中常用的方法

    1. 常用字段(常量)
      线程的优先级:1-10

       System.out.println("最高优先级:"+ Thread.MAX_PRIORITY);
       System.out.println("默认优先级:"+ Thread.NORM_PRIORITY);
       System.out.println("最低优先级:"+ Thread.MIN_PRIORITY);
      
    2. 优先级越高获得时间片的概率越大
      线程默认优先级都是:5

    3. 构造方法
      Thread():创建默认名字的线程。
      Thread(String name):创建一个指定名字的线程
      Thread(Runnable target) :根据传入Runnable对象创建线程,线程的名字是默认的
      Thread(Runnable target, String name) :根据传入Runnable对象创建线程,线程的名字是指定的

    4. 常用方法

      1. getName():获取线程名字
      2. currentThread() :获取当前线程
      3. getPriority() :获取线程的优先级
      4. setPriority(int newPriority) :设置线程优先级
      5. setName(String name) :设置线程名字
      6. sleep(long millis):设置线程休眠的时间
      7. 线程分为:前台线程,后台线程(守护线程)
        GC:垃圾回收机制(GC属于后台线程)
      8. isDaemon():判断线程是否位守护线程
      9. setDaemon(boolean on):设置线程位守护线程

    梳理线程

    ​ 线程的执行流程:

    1. 启动线程
    2. cpu分配时间片
    3. 拿到时间片的线程开始执行(run()的代码)
    4. 直到run()里面的代码执行完毕后,线程解结束
                交替执行
    

    java中实现多线程的方式:

    1. 继承Thread,重写run方法
    2. 实现Runnable接口
    

    创建线程,启动线程

    Thread常用的方法:

    1. 获取当前的线程
    2. 线程休眠
    3. 获取线程名字

    线程的状态:

    1. 新建 new Play();
    2. 就绪 new Play().start();
    3. 运行 执行run方法的时候
    4. 阻塞 sleep()
    5. 死亡(结束) run方法执行完毕