1.异常
1.0 异常的概念
2.throw关键字
public class Main{ public static void main(String[] args) { int []arc=null; getelem(arc,0); } private static int getelem(int arc[],int index) { if(arc==null){ throw new NullPointerException("空指针异常!"); } return arc[index]; } }
public class Main{ public static void main(String[] args) { int []arc=new int[3]; getelem(arc,3); } private static int getelem(int arc[],int index) { if(arc==null){ throw new NullPointerException("空指针异常!"); } else if(index>=arc.length||index<0) { throw new ArrayIndexOutOfBoundsException("下标超出数组的范围!"); } return arc[index]; } }
3.Objects 非空判断
import java.util.Objects; public class Main{ public static void main(String[] args) { int arc[]=null; Objects.requireNonNull(arc,"空指针异常"); } }
4.异常处理的第一种方法 throws关键字
import java.io.FileNotFoundException; import java.io.IOException; import java.lang.module.FindException; public class Main { public static void main(String[] args) throws Exception { //判断路径是否是C:\\.txt Filename("C:\\.tx"); } private static void Filename(String s) throws Exception { //FileNotFoundException extends IOException extends Exception if(!s.equals("C:\\.txt")){ throw new FileNotFoundException("该路径不是C:\\.txt"); } if(!s.endsWith(".txt")) throw new IOException("文件后缀不是.txt"); } }
5.异常处理的第二种方法
try...catch()
import java.lang.invoke.MethodHandles; public class Main{ public static void main(String[] args) { int[] arc=new int[3]; try { int getelem = getelem(arc, 3); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("程序由catch处理"); } System.out.println("后续代码"); //如果抛出throws 程序交给JVM处理 程序遇到异常就会中断 } private static int getelem(int arc[],int index) throws ArrayIndexOutOfBoundsException{ if(index<0||index>=arc.length) { throw new ArrayIndexOutOfBoundsException("下标超出数组的长度范围"); } return arc[index]; } }
打印结果:
程序由catch处理
后续代码
6.Throwable类中常用的方法
import java.lang.invoke.MethodHandles;
public class Main{
public static void main(String[] args) {
int[] arc=new int[3];
try {
int getelem = getelem(arc, 3);
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e.getMessage());
System.out.println(e.toString());
System.out.println(e);
e.printStackTrace();
}
System.out.println("后续代码");
//如果抛出throws 程序交给JVM处理 程序遇到异常就会中断
}
private static int getelem(int arc[],int index) throws ArrayIndexOutOfBoundsException{
if(index<0||index>=arc.length)
{
throw new ArrayIndexOutOfBoundsException("下标超出数组的长度范围");
}
return arc[index];
}
}
打印结果:
下标超出数组的长度范围
java.lang.ArrayIndexOutOfBoundsException: 下标超出数组的长度范围
java.lang.ArrayIndexOutOfBoundsException: 下标超出数组的长度范围
后续代码
java.lang.ArrayIndexOutOfBoundsException: 下标超出数组的长度范围
at Main.getelem(Main.java:24)
at Main.main(Main.java:7)
7.异常处理的注意事项
(1)多个异常对象
import java.util.List; /* * 异常处理:多个异常对象的处理 * 1、多个异常分别处理 * 2、多个异常一次捕获,多次处理 * 3、多个异常一次捕获一次处理 * */ public class Main{ public static void main(String[] args) { //int []arc=new int[3]; //System.out.println(arc[3]);//ArrayIndexOutOfBoundsException 3 //Listlist = List.of(4, 3, 26, 6); //System.out.println(list.get(4));//IndexOutOfBoundsException /*1.多个异常分别处理 try{ int []arc=new int[3]; System.out.println(arc[3]); }catch(ArrayIndexOutOfBoundsException e) { System.out.println(e); } try{ List list = List.of(4, 3, 26, 6); System.out.println(list.get(4)); }catch(IndexOutOfBoundsException e) { System.out.println(e); } java.lang.ArrayIndexOutOfBoundsException: 3 java.lang.IndexOutOfBoundsException: Index 4 out-of-bounds for length 4 */ /* 2.多个异常一次捕获多次处理 注意事项 子类对象必须写在父类对象之上 try{ int []arc=new int[3]; System.out.println(arc[3]); List list = List.of(4, 3, 26, 6); System.out.println(list.get(4)); } catch(ArrayIndexOutOfBoundsException e){ System.out.println(e); } catch (IndexOutOfBoundsException e) { System.out.println(e); } } */ /* 3、多个异常一次捕获一次处理 try{ int []arc=new int[3]; System.out.println(arc[3]); List list = List.of(4, 3, 26, 6); System.out.println(list.get(4)); } catch(Exception e) { System.out.println(e); } } */ } }
(2)finally代码块里有return语句
public class Main{ public static void main(String[] args) { int method = method(); System.out.println(method);//20 } private static int method() { try{ int a[]=null; int sum=0; return sum; }catch(NullPointerException e) { System.out.println(e); } finally { int sum=20; return sum; } } }
(3)子父类异常
public class FU { public void show1() throws NullPointerException, ClassCastException { } public void show2() throws IndexOutOfBoundsException { }; public void show3() throws IndexOutOfBoundsException { }; public void show4() { } } class ZI extends FU{ @Override public void show1() throws NullPointerException, ClassCastException { } public void show2() throws ArrayIndexOutOfBoundsException{} @Override public void show3(){} public void show4(){ try { throw new Exception("编译器异常"); } catch (Exception e) { e.printStackTrace(); } } }
(4)自定义异常类
public class ReadException extends Exception{ public ReadException() { } public ReadException(String message) {//添加一个带异常信息的构造方法 super(message); } }
(5)自定义异常的小练习
注册名称
public class RegisterException extends Exception { public RegisterException(String message) { super(message); } public RegisterException() { } }
1)通过throws方法处理异常
import java.util.Scanner; public class Register { public static String []name={"Mary","Lisa","Jennie","JK","Minnie"};//全局变量 public static void main(String[] args) throws RegisterException { System.out.println("请输入您要注册的姓名:"); Scanner input=new Scanner(System.in); String usename=input.next(); Checkname(usename); } public static void Checkname(String usename) throws RegisterException { for (String s : name) { if(s.equals(usename))//true { throw new RegisterException("对不起,您的名字已经被注册过!"); } } System.out.println("恭喜您,注册成功!"); } }
请输入您要注册的姓名:
jhfshdbfbsfhe
恭喜您,注册成功!
请输入您要注册的姓名:
Mary
Exception in thread "main" RegisterException: 对不起,您的名字已经被注册过!
at Register.Checkname(Register.java:16)
at Register.main(Register.java:9)
2)try...catch()处理
import java.util.Scanner;
public class Register {
public static String []name={"Mary","Lisa","Jennie","JK","Minnie"};//全局变量
public static void main(String[] args) {
System.out.println("请输入您要注册的姓名:");
Scanner input=new Scanner(System.in);
String usename=input.next();
Checkname(usename);
}
public static void Checkname(String usename){
for (String s : name) {
if(s.equals(usename))//true
{
try {
throw new RegisterException("对不起,您的名字已经被注册过!");
} catch (RegisterException e) {
e.printStackTrace();
return;
}
}
}
System.out.println("恭喜您,注册成功!");
}
}
3)也可以将RegisterException 继承RuntimeException
public class RegisterException extends RuntimeException { public RegisterException(String message) { super(message); } public RegisterException() { } }
import java.util.Scanner; public class Register { public static String []name={"Mary","Lisa","Jennie","JK","Minnie"};//全局变量 public static void main(String[] args) { System.out.println("请输入您要注册的姓名:"); Scanner input=new Scanner(System.in); String usename=input.next(); Checkname(usename); } public static void Checkname(String usename){ for (String s : name) { if(s.equals(usename))//true { throw new RegisterException("对不起,您的名字已经被注册过!"); } } System.out.println("恭喜您,注册成功!"); } }
2.线程
1.0 并发和并行
2.进程与线程
线程的概念以及对线程的分析
3.线程的调度
4.主线程
5.创建多线程程序
第一种创建方式
public class Mythread extends Thread { @Override public void run() { for(int i=0;i<5;i++) { System.out.println("run:"+i); } } }
public class Main{ public static void main(String[] args) { Mythread mt=new Mythread(); mt.start(); for(int i=0;i<5;i++) { System.out.println("Main:"+i); } } }
第一次打印结果:
Main:0
Main:1
run:0
Main:2
Main:3
run:1
Main:4
run:2
run:3
run:4
第二次打印结果:
Main:0
run:0
Main:1
run:1
Main:2
run:2
Main:3
run:3
Main:4
run:4
每次打印结果可能不同 因为多个线程并发 抢占式调度
两个线程 一个main线程 一个新线程 抢夺CPU(执行时间)
第二种方式
public class RunnableImpl implements Runnable{ @Override public void run() { for(int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"--->"+i); } } }
public class Main{ public static void main(String[] args) { RunnableImpl impl=new RunnableImpl(); Thread t=new Thread(impl); t.start(); for(int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"--->"+i); } } }
打印结果:
main--->0
main--->1
Thread-0--->0
main--->2
Thread-0--->1
Thread-0--->2
main--->3
Thread-0--->3
main--->4
Thread-0--->4
实现Runnable接口创建多线程程序的好处
6.Thread类常用方法
(1)获取线程名称
(2) 设置线程的名称
public class Mythread extends Thread { public Mythread(String name) { super(name); } public Mythread() { } @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
public class Main{ public static void main(String[] args) { Mythread mt=new Mythread(); mt.setName("START");//START mt.start(); new Mythread("Hello").start();//Hello } }
(3)sleep方法
一秒打印一个数
public class Main{ public static void main(String[] args) { for (int i = 1; i <=10 ; i++) { System.out.println(i); try{ Thread.sleep(1000); }catch(InterruptedException e) { e.printStackTrace(); } } } }
7.匿名内部类方式实现线程的创建
public class Main{ public static void main(String[] args) { /*第一种创建方式 new Thread(){ @Override public void run() { for(int i=1;i<=5;i++) { System.out.println(Thread.currentThread().getName()+"->"+i); } } }.start(); */ /*第二种通过Runnable接口 (1) Runnable r=new Runnable() { @Override public void run() { for(int i=1;i<=5;i++) { System.out.println(Thread.currentThread().getName()+"->"+i); } } }; new Thread(r).start(); (2)简化版本 new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=5;i++) { System.out.println(Thread.currentThread().getName()+"->"+i); } } }).start(); */ for(int i=1;i<=5;i++) { System.out.println(Thread.currentThread().getName()+"->"+i); } } }
3.线程安全问题
1.0 概述
2.线程安全问题产生
public class RunnableImpl implements Runnable{ private int ticket=100; @Override public void run() { while(true) { if(ticket>0) { try{ Thread.sleep(100); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票"); ticket--; } } } }
public class Main{ public static void main(String[] args) { RunnableImpl r=new RunnableImpl(); Thread r1=new Thread(r); Thread r2=new Thread(r); Thread r3=new Thread(r); r1.start(); r2.start(); r3.start(); } }
结果中出现 1 0 -1 不存在的票说明 在共享数据的同时发生了安全性问题
3.解决线程安全问题
(1)第一种方式 同步代码块
public class RunnableImpl implements Runnable{ private int ticket=100; Object obj=new Object() ; @Override public void run() { while(true) { synchronized (obj) { if(ticket>0) { try{ Thread.sleep(100); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票"); ticket--; } } } } }
同步技术的原理
(2)第二种方法 同步方法
public class RunnableImpl implements Runnable{ private int ticket=100; @Override public void run() { while(true) { payticket(); } } public synchronized void payticket() { if(ticket>0) { try{ Thread.sleep(100); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票"); ticket--; } } }
------静态同步方法
(3)第三种方式 Lock锁
写法一:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; 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(100); }catch(Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票"); ticket--; } l.unlock(); } } }
写法二(效率高)
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; 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(100); System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票"); ticket--; }catch(Exception e) { e.printStackTrace(); }finally { l.unlock(); } } } } }
4.线程状态
1.0 概述
2.0等待唤醒案例
分析卖包子案例
代码实现
public class Sale { 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(); } }
打印结果:
顾客告诉老板自己的需求
老板5秒做好了包子
美味的包子已经做好,开吃!
Object类中 wait带参方法以及notify方法
3.等待唤醒机制
案例
public class Baozi { String Pi; String Xian; boolean falg=false; }
public class Baozipu extends Thread { private Baozi baozi; public Baozipu( Baozi baozi) { this.baozi = baozi; } @Override public void run() { int count=0; while(true) { synchronized (baozi) { //包子状态 有 if(baozi.falg==true) { try { baozi.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //生产包子 if(count%2==0) { baozi.Pi="薄皮"; baozi.Xian="猪肉玉米"; } else { baozi.Pi="凉皮"; baozi.Xian="牛肉三鲜"; } count++; System.out.println("正在做"+baozi.Pi+baozi.Xian+"的包子"); try { Thread.sleep(5000);//5秒生产 } catch (InterruptedException e) { e.printStackTrace(); } baozi.falg=true; baozi.notify(); System.out.println(baozi.Pi+baozi.Xian+"的包子已经做好 开吃!"); } } } }
public class Chihuo extends Thread { private Baozi baozi; public Chihuo(Baozi baozi) { this.baozi = baozi; } @Override public void run() { while(true) { synchronized (baozi) { if(baozi.falg==false) { try { baozi.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //唤醒后 System.out.println("吃货正在吃:"+baozi.Pi+baozi.Xian+"的包子"); baozi.falg=false; baozi.notify(); System.out.println("吃货已经吃完,继续生产"); System.out.println("----------------------"); } } } }
测试类(顾客)
public class Main{ public static void main(String[] args) { Baozi bz=new Baozi(); new Baozipu(bz).start(); new Chihuo(bz).start(); } }
5.线程池
public class RunnableImpl implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"正在执行"); } }
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main{ public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(2); pool.submit(new RunnableImpl());//pool-1-thread-1正在执行 pool.submit(new RunnableImpl());//pool-1-thread-2正在执行 //只有两个线程 线程池会一直开启 一个线程结束后归还 可以继续使用 pool.submit(new RunnableImpl());//pool-1-thread-1正在执行 pool.shutdown();//销毁线程池 } }
6.函数式编程思想
1.0 概述
2.0体验Lambda的更优
public class Main{ public static void main(String[] args) { new Thread() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在执行"); } }.start(); System.out.println("----------"); new Thread(() -> { System.out.println(Thread.currentThread().getName() + "正在执行"); }).start(); } }
打印结果:
----------
Thread-1正在执行
Thread-0正在执行
3.0 Lambda标准格式
(1)无参数无返回值
public interface Cook { public abstract void makefood(); }
public class Main{ public static void main(String[] args) { show(()->{ System.out.println("吃饭啦!德善"); } ); } public static void show(Cook cook) { cook.makefood(); } }
打印结果:
吃饭啦!德善
(2)有参数有返回值
对年龄进行排序
import java.util.Arrays; import java.util.Comparator; public class Main{ public static void main(String[] args) { Person[] person = {new Person("V", 25), new Person("JK", 23), new Person("Jin", 27)}; /* Arrays.sort(person, new Comparator() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge();//升序 } }); */ Arrays.sort(person,(Person o1, Person o2) -> { return o1.getAge()-o2.getAge(); }); for (Person person1 : person) { System.out.println(person1.getName()+" "+person1.getAge()); } } }
打印结果:
JK 23
V 25
Jin 27
4.0 lambda可省略