异常
异常的概念与体系
异常的分类
public static void main(String[] args) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = simpleDateFormat.parse("202106-01"); //ParseException
System.out.println(date);
}
public static void main(String[] args) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = simpleDateFormat.parse("202106-01");//ParseException
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("后续代码");
System.out.println(date);
}
int[] a = new int[3];
System.out.println(a[3]); //ArrayIndexOutOfBoundsException
int[] a = new int[1024*1024*1024];
System.out.println(a[3]);//OutOfMemoryError
异常的产生过程
【注意】JVM在其中有着巨大的作用
异常的处理
异常处理的5个关键字:try,catch,finally,throw,throws.
throw关键字
public static int getElement(int[] arr,int index) {
if (arr == null) {
// NullPointerException运行期异常(runtimeException
throw new NullPointerException("传递的数组是空");
}
if (index < 0 || index >= arr.length) {
//ArrayIndexOutOfBoundsException是运行期异常(runtimeException
throw new ArrayIndexOutOfBoundsException("数组越界了!");
}
return arr[index];
}
objects的方法
下边的写法是等价的
Objects.requireNonNull(arr, "传递的数组是空");
/*if (arr == null) {
// NullPointerException运行期异常
throw new NullPointerException("传递的数组是空");
}*/
throws关键字:异常的第一种处理方法
try…catch: 异常的第二种使用方法
public static void main(String[] args) {
try {
readFile("d:\\a.tx");
} catch (IOException e) {
System.out.println("文件路径不对");
}
System.out.println(666666666);
}
public static void readFile(String fileName) throws IOException{
if (!fileName.endsWith(".txt")) {
throw new IOException("文件的后缀名不对!");
}
}
throwable类的3个异常处理
finally代码块
多异常的捕获处理
finally中有return语句
【注意】尽量避免finally中有return语句。
字符类异常
自定义异常类
多线程
并发与并行
进程
程序和进程
线程
线程调度
分时调度
抢占式的(优先级,否则随机),Java使用的是抢占式。
主线程(main线程)
主线程:执行主(main)方法的线程
单线程程序:Java程序中只有一个线程
执行从main开始,从上到下依次执行
创建多线程的第一种方法(继承Thread类)
多线程原理
多线程原理_多线程内存图解
【注意】栈空间
线程的名称
设置线程的名称
常用方法——Sleep
【注意】,是对当前线程的,可以使用Thread的静态方法。
创建多线程程序的第二种方式
public class Demo01Runnable implements Runnable {
@Override
public void run() {
System.out.println("run");
}
}
public static void main(String[] args) {
Demo01Runnable demo01Runnable = new Demo01Runnable();
new Thread(demo01Runnable).start();
}
使用接口的好处(thread和runnable的区别)
匿名内部类实现线程
public class Demo01InnerClassThread {
public static void main(String[] args) {
new Thread(){
@Override
public void run(){
for (int i = 0; i < 20; i++) {
System.out.println("liu"+"--->"+i);
}
}
}.start();
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("chun"+"--->"+i);
}
}
};
new Thread(r).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("lei"+"--->"+i);
}
}
}).start();
}
}
线程同步机制
线程安全概述
多线程访问了共享的数据,会产生线程安全问题。
public class Demo05Test {
public static void main(String[] args) {
//创建一个实现类对象,供三个线程进行调用
RunnableImpl r = new RunnableImpl();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);
//开启线程
t1.start();
t2.start();
t3.start();
}
}
线程安全问题产生的原理
解决线程安全的方法
1.同步代码块
2.同步方法
3.锁机制
1.同步代码块
private int ticket=100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized(obj) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->正在卖第" + ticket + "张票");
ticket--;
}
}
}
}
同步技术的原理
2.同步方法
public synchronized void ticketSent(){
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "--->正在卖第" + ticket + "张票");
ticket--;
}
}
静态同步方法
【注意】RunnableImpl.class也可以加锁
3.Lock锁
public class RunnableImpl implements Runnable {
private int ticket=100;
Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
l.lock();
if (ticket > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + "--->正在卖第" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();//无论程序是否异常,都会释放锁
}
}
}
}
}
线程等待唤醒机制
线程状态图
等待唤醒案例
public static void main(String[] args) {
Object obj = new Object();
new Thread(){
@Override
public void run() {
synchronized (obj) {
System.out.println("告诉老板信息");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("拿到包子了");
}
}
}.start();
new Thread(){
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("老板花了5秒,做好包子了");
obj.notify();
}
}
}.start();
}
【注意】notify是随机的唤醒一个等待线程
线程间的通信(对资源的使用需要商量着来)
等待唤醒机制
线程池:频繁创建和销毁线程太耗费资源,线程池可以复用线程
线程池