一、异常
1、异常的涵义
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:
两种:一种是严重的问题,一种非严重的问题。
对于严重的,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理。
对与非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。
比如:不正常情况的信息,引发原因等。
Throwable
|--Error
|--Exception
异常的常见的相关代码:
Throwable
Throwable表示Java中可被抛出的对象,它是所有错误和异常的父类
Throwable有两个子类:Error、Exception
Error表示错误
Exception表示异常
RuntimeException表示运行时异常,是Exception的子类
2、异常的处理
java 提供了特有的语句进行处理。
try
{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句;
}
3,对捕获到的异常对象进行常见方法操作。
String getMessage():获取异常信息。
在函数上声明异常。
便于提高安全性,让调用出进行处理。不处理编译失败。
class Demo
{
int div(int a,int b)throws Exception//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
return a/b;
}
}
3、自定义异常
涵义:
因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想。将特有的问题。进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理。要么在函数上声明让调用者处理。一般情况在,函数内出现异常,函数上需要声明。
自定义异常:
必须是自定义类继承Exception。
继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。
throws和throw的区别
(1)throws使用在函数上,hrow使用在函数内。
(2)throws后面跟的异常类。可以跟多个。用逗号隔开。throw后跟的是异常对象。
二、多线程
1、进程和线程
进程:
是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:
就是进程中的一个独立的控制单元。线程在控制着进程的执行,一个进程中至少有一个线程。Java VM 启动的时候会有一个进程java.exe.该进程中至少一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。
其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
2、在自定义的代码中自定义一个线程的方法
通过对api的查找,java已经提供了对线程这类事物的描述。就Thread类。
创建线程的第一种方式:继承Thread类。
步骤:
(1)定义类继承Thread。
(2)复写Thread类中的run方法。
目的:将自定义代码存储在run方法。让线程运行。
(3)调用线程的start方法,
该方法两个作用:启动线程,调用run方法。
发现运行结果每一次都不同。因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。
明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)cpu在做着快速的切换,以达到看上去是同时运行的效果。也可以说多线程的运行行为在互相抢夺cpu的执行权。这就是多线程的一个特性:随机性。
(4)覆盖run方法的原由
Thread类用于描述线程。
该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。也就是说Thread类中的run方法,用于存储线程要运行的代码。
创建线程的第二种方式:实现Runable接口
步骤:
(1),定义类实现Runnable接口
(2),覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
(3),通过Thread类建立线程对象。
(4),将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象传递给Thread的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。
(5),调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
实现方式和继承方式有什么区别呢?实现方式好处:避免了单继承的局限性。在定义线程时,建立使用实现方式。
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
3、线程的安全问题
(1)安全问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
(2)解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。Java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。
如下:
synchronized(对象)
{
//需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
(3)同步的前提:
必须要有两个或者两个以上的线程。
必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
(4)同步的优缺点
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源
解决线程安全的另一个方法就是同步函数,将锁synchronized只要函数中即可。
4、停止线程
如何停止线程?
只有一种,run方法结束。
特殊情况:当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();