A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yangxiaoqiang 初级黑马   /  2018-11-20 16:23  /  766 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Day5:异常 多线程
1:异常的分类及解释
1:异常继承体系为:异常的根类是 java.lang.Throwable,其下有两个子类:java.lang.Error 与 java.util.Exception 。而Exception又分为编译时期异常:checked异常,与运行时期异常:runtime异常。
2:Error:表示不可修复的恶性的错误,只能通过修改代码规避错误的产生,通常是系统级别的,所以很严重。
3:Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且应该通过代码的方式纠正,使程序继续运行,是必须要处理的。
4:运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。
2:异常的的处理方式
一:throws声明抛出异常
   throws, 声明抛出 (方法自己不处理, 交给方法调用者处理, "甩锅给别人")
   作用: 告诉方法的调用者, 调用此方法有可能发生异常, 需要在编写代码时处理
throw关键字作用: 在方法中制定的异常对象
格式:
throw new 异常类名("异常原因字符串"); 注意: new 的对象必须是"Exception" 或 "Excetion的子类" 的对象

throw和throws的区别
1:throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行。
2:throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处
二:捕获异常
try...catch...finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行
格式:


    try {
        // 可能产生异常的代码
    } catch (异常类名 变量名) {
        // 处理异常的代码
        // 一般会将异常信息存储到日志中
    }
    ...
    } finally (异常类名 变量名) {
        // 处理异常的代码
        // 无论是否发生异常,都必须执行的代码块
    }


3:Throwable中的3个异常处理方式java.lang.Throwable
    // 成员方法
    String getMessage(): 异常的信息. 没有原因返回null
    String toString(): 异常的类型和原因信息
    void printStackTrace(): 使用标准错误输出流打印异常信息(常用方式)

4:异常处理注意事项
1:异常存在继承关系,子类异常在上,父类异常在下,多个异常用Excption多态捕获
2:finally代码块中如果有return语句,返回的是return语句的值
3:如果父类抛出多个异常,①抛出和父类相同的异常 ②抛出父类异常的子类 ③不抛出异常
父类没有抛出异常,子类重写父类方法时也不能抛出异常,如果子类产生该异常,只能捕获处理
自定义异常类: ①定义编译时异常: 继承 Exception ②定义运行时异常: 继承RuntimeException
5:多线程
1:并发:(交替执行) 指两个或多个事件在同一时间段内发生 2:并行:(同时执行) 指两个或多个事件在同一时间发生
3:线程:代码执行的路径. 一个程序运行至少有一个进程,进程可以包含多个线程
多线程好处: 效率高, 多个线程之间互不影响
4:线程调度: ①分时调度:所有线程轮流使用cpu,平分占用cpu的时间 ②抢占式调度:优先级相同,随机选择一个线程执行
Day6:线程 同步 线程间通信
一:线程
1:Thread类

第一种方式:继承Thread类
         1.定义一个子线程的类,继承Thread类;
        2.在子线程类中重写run方法,
       3.定义一个测试类;
       4.在main方法中创建子线程对象;
        5.调用子线程对象的start方法,开启子线程
java.lang.Thread类: 表示线程.
// 成员方法
    void run(): 用于让子类重写, 表示该线程要执行的任务.不能直接调用
    void start(): 启动线程, 即让线程开始执行run()方法中的代码
    String getName(): 获取线程的名称
    void setName(String name): 设置线程名称
    // 静态方法   
    static Thread currentThread(): 返回对当前正在执行的线程对象的引用
    static void sleep(long millis): 让所在线程睡眠指定的毫秒



2:实现Runnable接口
第二种方式:实现Runnable接口
1.定义一个子任务类,实现Runnable接口;
2.在子任务类中重写run方法,
3.定义一个测试类;
4.在main方法中创建一个子任务对象;
5.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的构造方法;
6.调用Thread类对象的start方法开启子线程;
优势:
1:避免单继承的局限性 2增强程序的扩展性,降低程序的耦合性(解耦)
3:匿名内部类
public class Test {
    public static void main(String[] args) {
        // 匿名内部类方式
        new Thread(new Runnable(){
            @Override
            public void run() {
                // 要执行的任务
            }
        }).start();
    }
}

4:线程安全的产生及解决方式
原因:多个线程操作共享资源,由于JVM是抢占式调度,一个线程没有执行完,另一个线程就来操作,就会出现问题
:线程安全解决方式1:同步代码块
锁对象可以是任意类型对象,必须是被多个线程共享的唯一的对象, 作用: 只让一个程序在同步代码块中执行
格式:
    synchronized (锁对象) {
        // 操作共享数据的代码
        
    }



:线程安全解决方式2:同步方法
非静态方法的锁对象:this
// 非静态同步方法
    public synchronized void method(){
        // 可能会产生线程安全问题的代码
    }
静态同步方法的对象:字节码对象 class对象
获取一个类的字节码对象的3种方式:
    1. 对象名.getClass()          new RunnableImpl().getClass()
    2. 类名.class                 RunnableImpl.class
    3. Class.forName("类的全名");  Class.forName("com.itheima.test05.RunnableImpl");



:线程安全解决方式3:Lock锁
java.util.concurrent.locks.Lock接口:
使用方式:
public class RunnableImpl implements Runnable {
    // 成员变量创建锁对象, 该锁对象也要所有线程共享唯一一个
    Lock lock = new ReentrantLock();  // 成员变量


    @Override
    public void run() {
        // 加锁
        lock.lock();
        try {
            // 操作共享变量的代码...
        } finally {
            // 在finally中保证释放锁
            lock.unlock();  
        }
    }
}



:线程间的通信
线程的生命周期中, 可以出现有6种状态:
    1. "NEW 新建"
       线程被创建, 但没有调用 start() 启动
    2. "RUNNABLE 可运行"
       调用 start()方法后已启动, 但可能正在执行 run() 方法的代码, 也可能正在等待CPU的调度
    3. "BLOCKED (锁)阻塞"
       线程试图获取锁, 但此时锁被其他线程持有
    4. "WAITING 无限等待"
       通过锁对象调用无参的 wait() 进入此状态.
       等待其他线程通过锁对象执行 notify() 或 notifyAll() 才能结束这个状态
    5. "TIMED_WAITING 计时等待"
       如通过锁对象调用有参的 wait(long millis) 或 sleep(long millis), 则进入此状态.
       直到时间结束之前被其他线程通过锁对象执行 notify()或 notifyAll()唤醒, 或时间结束自动唤醒
    6. "TERMINATED 终止"
       run()方法结束(执行结束, 或内部出现异常), 则进入此状态
(notify():随机唤醒一条线程 notifyAll():唤醒所有的线程 wait():让当前线程处于"无限等待"状态)通过锁对象调用





0 个回复

您需要登录后才可以回帖 登录 | 加入黑马