第五天Java基础(异常)
1.异常(Excption)
1.1 异常分类
1.Exception:编译异常
2.RuntimeException:运行异常
3.Error:错误
1.2异常的两种处理方式
1.抛出异常,JVM处理异常,如果发现异常直接中断程序,控制台打印异常。
throws ParseException {
//把异常交给JVM处理
}
2.自行处理异常
try {
date = sf.parse("1999-1203000");
}catch (ParseException e){
e.getErrorOffset();
}
3.异常抛出的处理流程
1.2 关键字(throw)
1.写在方法内部
2.new的对象必须是Exception或是其子类
throw new NullPointerException("抛异常");
3.我们必须对方法传递过来的参数进行合法性的校验,如果不合法就抛异常。
1.3Object非空判断
Objects.requireNonNull(obj,“异常描述”);//该方法对对象进行非空校验,如果为空直接抛异常。
1.4关键字(throws)
1.必须写在方法声明处。
2.声明的对象必须是Exception或是其子类。
3.方法抛出多个异常对象,throws也必须声明多个异常。
4.必须处理异常。(自己处理,或者jvm中断程序)
1.5关键字(try_catch)
1.try中可能会抛出多个异常对象,那么就需要使用多个catch,来捕获异常,
2.try代码中一但出现异常,就会执行catch去处理错误,然后继续执行后续代码。
1.6Throwable类中定义的三个异常处理方法
1.getMessage();//返回简短信息
2.toString();//详细信息
3.printStackTrace();//全面信息
try {
}catch (Exception e){
e.getMessage();//简短
e.toString();//详细信息
e.printStackTrace();//全面信息
}
1.7(关键字)finally
try{}catch(){}finally{
//无论是否出现异常都会执行
//主要用于资源释放
}
1.8 异常的注意事项
1.如果异常类型出现父子关系,那么子类必须写在前面。
2.父类可以同时接收子类的异常。
3.如果finally中出现return关键字返回的结果都是finally中的结果
4.父类异常怎么了,子类异常就怎么样
1.9 自定义的异常类
1.自定义的异常类一定要继承Exception / RuntimeException
2.Exception 编译期异常
3.RuntimeException 运行异常
2 多线程
2.1 并发,并行
1.并发:多个事件在同一个时间段内发生。(交替执行)
2.并行:多个事件在同一个时刻内发生。(同时执行)
2.2 线程,进程
1.进程:进入到内存中的程序。
2.线程:线程是属于进程中的一个执行单元。
2.3 线程调度
1.分时调度:平均分配cpu使用时间
2.抢占式调度:工具优先级分配cpu使用时间
2.4 主线程
1.执行主方法的线程
2.5 多线程(Thread)常用的方法
1.getName();//获取线程名称
2.start();//开启线程
3.run();//重写线程方法
4.currentThread();//获取当前执行的线程,静态
5.Thread.currentThread().getName();//获取当前执行的线程,并打印名称
6.setName();//设置线程名称
7.在线程的子类中创建一个带参构造方法String name,super(name)把线程名字传递给Thread,也可以设置线程名。
8.Thread.sleep(1000);//线程暂停时间
2.6 多线程(Runnable)常用的方法
1.runnable开启线程的方式
实现Runnble接口,RunnbleImpl run = new RunnbleImpl();
创建Thread的构造方法,把run传进去,Thread t = new Thread(run);
然后开启线程
2.Runnable的好处
避免单继承的局限性
增强了程序的扩展性,降低类耦合性,把设置任务和开启线程进行分离
2.7 匿名内部类,简化线程代码
1.new Thread(){ run(){ … } }.start();
2.new Thread(new Runnale(){ run( … ) }).start();
2.8 线程安全问题
1.多线程在操作同一个资源时,会出现线程安全问题。
2.如何解决,同步技术
synchronized(锁对象){
//代码块
}
int count = 100;
Object obj = new Object();
@Override
public void run() {
while(true){
synchronized(obj){
if(count>0){
System.out.println(Thread.currentThread().getName()+",在买第"+count+"张票!");
--count;
}else{
break;
}
}
}
}
3.如何解决,同步方法
也是synchronized关键字,把产生线程安全问题的代码放入其中
同步方法:public synchronized void xxx(){}
其锁对象是this
4.静态同步方法:public static synchronized void xxx(){}
其锁对象是本类的class属性,class文件对象。
5.lockes锁 :
lockes锁比synchronized 锁 好一点。
其中两个方法比较重要
lock();//获取锁
unlock();//释放锁
Lock l =new ReentrantLock();
l.lock();//获取锁
l.unlock();//释放锁
3.线程状态
1.新建状态 new
2.运行状态 Runnable
3.阻塞状态 Blocked
4.死亡状态 Terminated
5.休眠状态 Timed_waiting
6.无限等待 Waiting
运行状态的线程可以通过
Object.wait()方法进入无限等待状态
可以通过Object.notify()恢复运行状态,或者是休眠状态
4.等待唤醒案例
public static void main(String[] args) {
Object o = new Object();
new Thread(){
@Override
public void run() {
while(true){
synchronized (o){
System.out.println("老板我要包子一个!");
try{
o.wait();
}catch(InterruptedException e){
System.out.println(e.getMessage().toString());
}
System.out.println("-------------------------------");
System.out.println("吃包子!");
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
try{
Thread.sleep(5000);
}catch(InterruptedException e){
System.out.println(e.getMessage().toString());
}
synchronized (o){
System.out.println("包子好了!");
o.notify();
}
System.out.println();
}
}
}.start();
}
5.Object类中wait带参数的方法
1.obj.wait(5000);//相当于Thread.sleep(5000);
2.唤醒线程的两种方法,obj.notify();//唤醒一个等待线程,obj.notifyall();//唤醒所有等待的线程
5.线程通信
1.主要通过锁对象调用,obj.notify();和obj.wait();
6.等待与唤醒
1.等待与唤醒机制必须在同步锁当中。
@Override
public void run() {
while(true){
synchronized (o){
System.out.println("老板我要包子一个!");
try{
o.wait();
}catch(InterruptedException e){
System.out.println(e.getMessage().toString());
}
System.out.println("-------------------------------");
System.out.println("吃包子!");
}
}
}
///////////////////////////////////////////////
@Override
public void run() {
while(true){
try{
Thread.sleep(5000);
}catch(InterruptedException e){
System.out.println(e.getMessage().toString());
}
synchronized (o){
System.out.println("包子好了!");
o.notify();
}
System.out.println();
}
}
5.线程池(Executors)
1.使用线程池的工厂类Executors里面提供的newFixedThreadPool生产一个指定数量的线程池
2.创建一个类来实现Runable,重写run();
3.调用ExecutorService中的方法submit,传递线程任务,开启线程执行run方法
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(new RunnableImpl);
es.shutdown();//销毁线程池
# 5.线程池(Executors)
6.Lambda表达式
1.主要简化匿名内部类的写法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("普通写法");
}
}).start();
new Thread(() -> {
System.out.println("Lambda表达式");
}).start();
2.省略规则
(参数列表):括号中参数列表类型,可以省略
(参数列表):括号中的参数只有一个,那么类型的()都可以省略
(一些代码):如果代码只有一行,无论是否有返回值都可以省略({},return,分号)注意一定要一起省略
new Thread(()-> System.out.println("sss")).start();
//////////////////////////////
Arrays.sort(arr, (Pan o1, Pan o2) -> o1.getAge() - o2.getAge());
3.Lambda的使用前提
使用必须具有接口,且接口必须仅有一个抽象方法
方法的参数或者局部变量必须为接口类型