异常
概念:java
指的就是程序在执行过程当中,出现的非正常的状况,最终会致使JVM的非正常中止
异常体系:程序员
java.lang.throwable : 异常的顶级
子类:安全
1.Exception 表示异常,异常产生后程序员能够经过代码的方式纠正,使程序继续运行, 必需要处理的. 2.Error 严重那个错误Error,没法经过处理的错误只能事先避免, 经常使用方法: 1. public void printStackTrace():打印异常的详细信息 包含了异常的类型,异常的缘由,还包括异常出现的位置,在开发和调试阶段,都得使用 printStackTrace. 2.public String getMessage(): 获取发生异常的缘由 提示给用户的时候,就提示错误缘由, 3.public String toString(); 获取异常的类型和异常描述信息(不用) 分类: 1. 编译时期异常: checked异常,在编译时期,就会检查,若是没有处理异常,则编译失败(如 日期格式化异常) 举例:ArrayIndexOutOfBoundsException NullPointerException ClassCastException IndexOutOfBoundsException ConcurrenModificationException 2. 运行时期异常: runtime异常,在运行时期,检查异常,在编译时期,运行异常不会编译器检 测 (不报错).(如数学异常) 举例: FileNotFoundException IoException ParseException 异常的产生过程解析
工具类:
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
6
public class ArrayTools{
public static int getElement(int[] arr, int index) {多线程
int element = arr[index]; return element;
}
}
测试类:
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
public class ExceptionDemo {
public static void main(String[] args){并发
int[] arr = ArrayTools.getElement(arr, 4) System.out.println("num=" + num); System.out.println("over");
}
}
图解:ide
第二章 异常的处理工具
关键字: try, catch, finally, throw, throws throw 用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法执行. 格式: throw new 异常类名(参数); throws 概念: 声明异常,将问题标识出来,报告给调用者,若是方法内用过throw抛出了编译时异常,而没有 捕获处理,那么将经过throws进行声明,让调用者去处理,,,,,,用在方法声明之上,用于表示当 前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常). 格式: 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2...{ } try....catch 概念: 捕获异常 try:该代码块中编写可能产生异常的代码。 try异常 最后只会抛出一个异常 若是没有捕获到 交给java虚拟机 catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理 在开发中也能够在catch将编译器异常转换成运行期异常处理 若是异常出现的话,会马上终止程序,若是不想程序终止,因此咱们得处理异常: 1. 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。 2. 在方法中使用try-catch的语句块来处理异常。 语法格式:
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
6
try{
编写可能会出现异常的代码
} catch(异常类型 e) {
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}测试
异常使用捕获处理的三种方式: 1.多个异常分别处理 2.多个异常一次捕获,屡次处理 (经常使用方式) 3.多个异常一次捕获一次处理 finally 代码块 有一些特定的代码不管异常是否发生,都须要执行,finally代码块中存放的代码都是必定会被 执行. ......当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,不然 finally永远会执行
异常注意事项:this
1.运行时异常被抛出能够不处理,即不捕获也不声明抛出 2.若是父类抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集 3.父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常,此时子类产生该异常, 只能捕获处理,不能声明抛出 4.当多异常处理时,捕获处理,前边的类不能是后边类的父类 5.在try/catch后能够追加finally代码块,其中的代码必定会被执行,一般用于资源回收 6.若是finally有return语句,永远返回finally中的结果,避免该状况
第三章 自定义异常类线程
定义: 1.自定义一个编译器异常:自定义类 并继承于java.lang.Exception 2.自定义一个运行时期的异常,:自定义类并继承于java.lang..RuntimeException. 处理自定义异常类: throws 自定义异常类类名 try catch(自定义异常类类名 变量)
第四章 多线程
并发: (交替执行)指两个或多个事件在"同一时间段内"发生 并行: (同时执行) 指两个或多个事件在"同一时刻"发生(同时发生) 进程: 内存中运行的一个应用程序. 每一个进程都有一个独立的内存空间,一个应用程序能够同时运行多个进程. 进程也是程序的一次执行过程,是系统运行程序的基本单位 系统运行一个程序便是一个进程从建立,运行到消亡的过程. 线程: 是进程内的一个独立执行单元(一条代码执行路径) 一个程序运行后至少有一个进程,一个进程中能够包含多个进程 多线程的好处: 效率高 多个线程之间互不影响 线程的调度: 多个线程要并发执行,那个线程被执行,那个线程不被执行,就是调度. 方式: 1.分时调度:全部线程轮流使用CPU,平分占用CPU的时间 2.抢占式调度:优先让优先级高的线程使用CPU;若是优先级相同,则随机选择一个 线程执行.
Java使用的是"抢占式"调度.
主线程:
咱们之前写的代码,也在一条线程中执行,该线程叫作"main线程",也成为"主线程. 若是没有额外建立线程,那么程序就只有一个线程,即主线程,此时程序是"单线程" 的单线程的执行特色;
同一个线程内的代码,从上往下一次执行.
建立多线程程序的第一种方式: 继承Thread类
实现多线程的第一种方式: 1.定义类,继承Thread类 2.重写run()方法,run方法内部是线程要执行的任务 3.建立Thread子类的对象,调用start()方法启动线程 java.lang.Thread类 : 表示线程,事项了Rannable接口 void start():启动线程,即让线程开始执行run()方法中的代码 注意: 必须调用start() 方法来开启线程,不能直接调用run() 方法,调用run()会变成 单线程同一线程对象,不能屡次调用start()方法 Java是抢占式调度,不一样线程的代码,执行顺序是随机的
第六天 线程、同步
第一章 线程
一、Java线程调度是抢占式的,多个线程互相抢夺CPU的执行权。CPU执行哪一个线程是随机的 二、多线程状况下,每一个线程都有各自的栈内存。 三、Thread类:表示线程,实现了Runnable接口
经常使用方法:
构造方法
[Java] 纯文本查看 复制代码
?
1
2
3
4
Thread(): 建立Thread对象
Thread(String threadName): 建立Thread对象并指定线程名
Thread(Runnable target): 经过Runnable对象建立Thread对象
Thread(Runnable target, String threadName)
成员方法
[Java] 纯文本查看 复制代码
?
1
2
3
4
void run(): 用于子类重写,表示线程执行任务,不能直接调用
void start(): 启动线程,让线程开始执行run()方法中的代码
String getName(): 获取线程的名称
void setName(String name): 设置线程名称
静态方法
[Java] 纯文本查看 复制代码
?
1
2
static Thread currentThread(): 返回对当前正在执行的线程对象的引用
void sleep(long mills): 让所在线程睡眠指定的毫秒
建立线程方式二:实现Runnable接口
定义Runnable接口实现类,重写run方法 建立Runnable实现类对象 建立Thread类对象,在构造方法中传入Runnable实现类对象 经过Thread对象调用start()方法启动线程
Thread和Runnable的区别
实现Runnable的好处: 一、避免单继承的局限性 二、加强了程序的扩展性,下降了程序的耦合性 (线程是Thread,任务是Runnable实现类对象,至关于将线程和任务分离)
匿名内部类方式建立线程
new Thread(new Runnable){ 重写run() }
线程安全问题
发生场景:多个线程操做共享资源 问题发生缘由: JVM是抢占式调度,CPU在每一个线程之间切换时随机的,代码执行到什么位置是不肯定的。 在操做共享资源时,一个线程还没执行完,另外一个线程就来操做,就会出现问题 解决多线程操做共享数据的安全问题 3种方式:同步代码块 同步方法 锁机制 同步代码块:使用synchronized关键字修饰的代码块,并传入一个看成锁的对象格式:
[Java] 纯文本查看 复制代码
?
1
2
3
synchronized(锁对象) {
//操做共享数据的代码
}
注意:锁对象能够是任意类型的一个对象 锁对象必须是被多个线程共享的惟一对象 锁对象的做用:只让一个线程在同步代码块中执行 同步的原理: 线程进入同步代码块前,会争夺锁对象,只有一个线程会抢到 进入同步代码块的线程,会持有锁对象,并执行代码块中的代码 此时同步代码块外的线程处于阻塞状态,只能等待 同步代码块内的线程执行完代码块,会离开同步代码块,并归还锁对象给同步代码块 此时同步代码块外的其余线程就能够继续争夺锁对象
同步方法:
非静态同步方法:(具备默认锁对象:this)
[Java] 纯文本查看 复制代码
?
1
2
3
public synchronized void method() {
//可能会产生线程安全问题的代码
}
静态同步方法
[Java] 纯文本查看 复制代码
?
1
2
3
public static synchronized void method() {
//可能会产生线程安全问题的代码
}
静态同步方法的锁对象:当前类的字节码对象 获取一个类的字节码对象的3种方式: 一、对象.getClass 二、类名.class 三、Class.forName(“类的全路径”) Lock锁 成员方法:
[Java] 纯文本查看 复制代码
?
1
2
void lock(): 获取锁
void unlock(): 释放锁
[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
public class RunnableImpl implements Runnable {
Lock lock = new ReentrantLock();
@override
public void run() {
lock.lock(); //加锁 try{ //操做共享变量的代码 } finally { lock.unlock(); //在finally中保证释放锁 }
}
}
线程安全和效率的特色
程安全,效率低 线程不安全,效率高
线程的状态
锁对象,也称为“同步锁”,“对象监视器”
Object类中关于线程的方法:
成员方法:
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
void notify(): 随机唤醒在同一个锁对象上的某一个处于等待状态的线程
void notifyAll(): 唤醒全部在同一个锁对象上处于等待状态的线程
void wait(): 让当前线程处于无限等待状态
void wait(long timeout): 让当前线程处于计时等待状态,时间到或被唤醒后结束此状态
void wait(ling timeout, int nanos): 让当前线程处于计时等待状态,时间到或被唤醒后结束此状态
线程的生命周期的6种状态:
一、NEW新建
线程被建立,但没有调用start()启动
二、RUNNABLE可运行
调用start()方法后已启动,但可能正在执行run()方法的代码,也可能正在等待CPU的调度
三、BLOCKED阻塞
线程试图获取锁,但此时锁被其余线程持有
四、WAITING无限等待
经过锁对象调用无参的wait()进入此状态 等待其余线程经过锁对象执行notify()或notifyAll()才能结束这个状态
五、TIMED_WAITINGj计时等待
如经过锁对象调用有参的wait(long millis)或sleep(long millis),则进入此状态 直到时间结束以前被其余线程经过锁对象执行notify()或notifyAll()唤醒,或时间结束自动唤醒
六、TERMINATED终止
run()方法结束(执行结束,或内部出现异常),则进入此状态
Object类成员方法:[Java] 纯文本查看 复制代码?12void notifyAll(): 唤醒全部在同一个锁对象上处于等待状态的线程void wait(long timeout): 让当前线程处于计时等待状态,时间到或被唤醒后结束此状态