java学习笔记<第三周>【Debug、异常、实现多线程、生产者消费者等】

Debug

1.1Debug概述

Debug:是供程序员使用的程序调试工具,它可以用于查看程序执行流程,也可以用于追踪程序执行过程来调试程序

1.2Debug操作流程

Debug调试,又被称为断点调试,断点其实是一个标记,告诉我们从哪里开始查看

  1. 如何加断点
  2. 如何运行加了断点的程序
  3. 看哪里
  4. 点哪里
  5. 如何删除断点

1.2.1如何加断点

选择要设置断点的代码行,在行号得到区域后面单击鼠标左键即可
请添加图片描述

1.2.2如何运行加了断点的程序

请添加图片描述

1.2.3看哪里

看Debugger窗口

请添加图片描述

看Console窗口

请添加图片描述

1.2.4点哪里

点Step Into(F7)这个箭头,也可以直接按F7

请添加图片描述

点Stop结束

请添加图片描述

1.2.5如何删除断点

选择要删除的断点,单击鼠标左键即可

请添加图片描述

1.2.5如何删除断点

如果是多个断点,可以每一个再点击一次,也可以一次性全部删除

请添加图片描述

1.3Debug使用

查看循环求偶数和的执行流程

1.4Debug使用

查看方法调用的执行流程

注意事项:

如果数据来自于键盘输入,一定要记住输入数据,不然就不能继续往下查看了

异常

1.1异常概述

异常:就是程序出现了不正常的情况

请添加图片描述

  • Error:严重问题,不需要处理

  • Exception:称为异常类,它表示程序本身可以处理的问题

  • RuntimeException:在编译期间,出现问题后,需要我们回来修改代码

  • 非RuntimeException:编译期就必须处理的,否则程序不能通过编译,就不更能正常运行了

1.2JVM的默认处理方案

如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理

  • 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
  • 程序停止执行
1.3异常处理

如果程序出现了问题,我们需要自己来处理,有两种方案:

  • try…catch…
  • throws
1.4异常处理之try…catch…

格式:

try{

​ 可能出现异常的代码;

}catch(异常类名 变量名){

​ 异常的处理代码;

}

执行流程:

  1. 程序从try里面的代码开始执行

  2. 出现异常,会自动生成一个异常类对象,该异常对象将被提交给java运行时系统

  3. 当java运行时系统被接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理

  4. 执行完毕后,程序还可以继续往下执行

1.5Throwable的成员方法

请添加图片描述

1.6编译时异常和运行时异常

java中的异常被分为两大类:编译时异常和运行时异常,也被称为受检异常和非受检异常

所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常

  • 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译

  • 运行时异常:无需显示处理,也可以和编译时异常一样处理

1.7异常处理之throws

虽然我们通过try…catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理

也就是说,有些时候可能出现的异常是我们处理不了的,这个时候该怎么办呢?

针对这种情况,java提供了throws的处理方案

格式

throws 异常类名;

注意:这个格式是跟在方法的括号后面的

  • 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,将来谁调用谁处理
  • 运行时异常可以不处理,出现问题后,需要我们回来修改代码
1.8自定义异常

格式:

public class 异常类名 extends Exception{

​ 无参构造

​ 带参构造

}

范例:

public class ScoreException extends Exception{

​ public ScoreException(){}

​ public ScoreException(String message){

​ super(message); }

}

实现多线程

1.1进程

进程:是正在运行的程序

  • 是系统进行资源分配和调用的独立单位
  • 每一个进程都有它自己的内存空间和系统资源
1.2线程

线程:是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进程如果只有一条执行路径,则成为单线程程序
  • 多线程:一个进程如果有多条执行路径,则称为多线程程序

举例

  • 记事本程序
  • 扫雷程序
1.3多线程的实现方式

方式一:继承Thread类

  • 定义一个类MyThread继承Thread类
  • 在MyThread类中重写run()方法
  • 创建MyThread类的对象
  • 启动线程

两个小问题:

  • 为什么要重写run()方法?

    因为run()是用来封装被线程执行的代码

  • run()方法和start()方法的区别?

    run():封装线程执行的代码,直接调用,相当于普通方法的调用

    start():启动线程;然后JVM调用此线程的run()方法

1.4设置和获取线程名称

Thread类中设置和获取线程名称的方法:

  • void setName(String name):将此线程的名称更改为等于参数name
  • String getName():返回此线程的名称
  • 通过构造方法也可以设置线程名称

如何获取main()方法所在的线程名称?

  • public static Thread currentThread():返回对当前正在执行的线程对象的引用
1.5线程调度

线程有两种调度模型

  • 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
  • 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一点

java使用的是抢占式调度模型

加入计算机只有一个CPU,那么CPU在某一时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的

Thread类中设置和获取线程优先级的方法:

  • public final int getPriority():返回此线程的优先级
  • public final void setPriority(int newPriority):更改此线程的优先级

线程默认优先级是5;线程优先级范围是:1-10

线程优先级高仅仅表示线程获取CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果

1.6线程控制

请添加图片描述

1.7线程生命周期

请添加图片描述

1.8多线程的实现方式

方式2:实现Runnable接口

  • 定义一个类MyRunnable实现Runnable接口
  • 在MyRunnable类中重写run()方法
  • 创建MyRunnable类的对象
  • 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
  • 启动线程

多线程的实现方案有两种

  • 继承Thread类
  • 实现Runnable接口

相比继承Thread类,实现Runnable接口的好处

  • 避免了java单继承的局限性
  • 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想

线程同步

2.3同步代码块

锁多条语句操作共享数据,可以使用同步代码块实现

格式:

synchronized(任意对象){

​ 多条语句操作共享数据的代码

}

synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁

同步的好处和弊端:

  • 好处:解决了多线程的数据安全问题

  • 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

2.4同步方法

同步方法:就是把synchronized关键字加到方法上

  • 格式:

​ 修饰符synchronized返回值类型 方法名(方法参数){}

同步方法的锁对象是什么呢?

  • this

同步静态方法:就是把synchronized关键字加到静态方法上

  • 格式:

​ 修饰符 staic synchronized 返回值类型 方法名(方法参数){}

同步静态方法的锁对象是什么呢?

  • 类名.class
2.5线程安全的类

StringBuffer

  • 线程安全,可变的字符序列
  • 从版本JDK5开始,被StringBuilder替代。通常应该使用StringBuilder类,因为它支持所有相同的操作,但它更快,因为他不执行同步

Vector

  • 从java2平台v1.2开始,该类改进了List接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Vector被同步。如果不需要线程安全的实现,建议使用ArratList代替Vector

Hashtable

  • 该类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或者值
  • 从java2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Hashtable被同步。如果不需要线程安全的实现,建议使用HashMap代替Hashtable
2.6Lock锁

虽然我们可以理解同步代码和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock实现提供比使用synchronized方法和语句可以获得更广法的锁定操作

Lock中提供了获得锁和释放锁的方法

  • void lock():获得锁
  • void unlock:释放锁

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

ReentrantLock的构造方法

  • ReentrantLock():创建一个ReentrantLock的实例

3.生产者消费者

3.1生产者消费者模式概述

生产者消费者是一个十分经典的多线程协作的模式,弄懂生产者消费者能够让我们对多线程编程的理解更加深刻

所谓生产者消费者问题,实际上主要包含了两类线程:

一类是生产者线程用于生产数据

一类是消费者线程用于消费数据

为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库

生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为

消费者只需要从共享数据区中去获取数据,并不需要关心生产者的行为

请添加图片描述

为了体现生产和消费过程中的等待和唤醒,Java就提供了几个方法供我们使用,这几个方法在Object类中Object类的等待和唤醒方法:

请添加图片描述

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值