JAVA自学笔记(6)—异常、线程、函数式编程

1.异常

1.0 异常的概念

 

 

JAVA自学笔记(6)—异常、线程、函数式编程_第1张图片

 

2.throw关键字

JAVA自学笔记(6)—异常、线程、函数式编程_第2张图片

 

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关键字

JAVA自学笔记(6)—异常、线程、函数式编程_第3张图片

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()

JAVA自学笔记(6)—异常、线程、函数式编程_第4张图片

 

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类中常用的方法

JAVA自学笔记(6)—异常、线程、函数式编程_第5张图片

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
        //List list = 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)自定义异常类

JAVA自学笔记(6)—异常、线程、函数式编程_第6张图片

 

 

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 并发和并行

JAVA自学笔记(6)—异常、线程、函数式编程_第7张图片

2.进程与线程

 JAVA自学笔记(6)—异常、线程、函数式编程_第8张图片

 

 

线程的概念以及对线程的分析

 

JAVA自学笔记(6)—异常、线程、函数式编程_第9张图片

 

3.线程的调度

JAVA自学笔记(6)—异常、线程、函数式编程_第10张图片

4.主线程

JAVA自学笔记(6)—异常、线程、函数式编程_第11张图片

 

5.创建多线程程序

第一种创建方式

JAVA自学笔记(6)—异常、线程、函数式编程_第12张图片

 

 

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(执行时间)

第二种方式

JAVA自学笔记(6)—异常、线程、函数式编程_第13张图片

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接口创建多线程程序的好处

 

JAVA自学笔记(6)—异常、线程、函数式编程_第14张图片

6.Thread类常用方法

(1)获取线程名称

JAVA自学笔记(6)—异常、线程、函数式编程_第15张图片

(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.匿名内部类方式实现线程的创建

JAVA自学笔记(6)—异常、线程、函数式编程_第16张图片

 

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 概述

JAVA自学笔记(6)—异常、线程、函数式编程_第17张图片

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();
    }
}

JAVA自学笔记(6)—异常、线程、函数式编程_第18张图片

结果中出现 1 0 -1 不存在的票说明 在共享数据的同时发生了安全性问题

3.解决线程安全问题

(1)第一种方式 同步代码块

JAVA自学笔记(6)—异常、线程、函数式编程_第19张图片

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--;
            }
        }
        }
    }
}

 

同步技术的原理

JAVA自学笔记(6)—异常、线程、函数式编程_第20张图片

 

 

(2)第二种方法 同步方法

JAVA自学笔记(6)—异常、线程、函数式编程_第21张图片

 

JAVA自学笔记(6)—异常、线程、函数式编程_第22张图片

 

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--;
        }
    }
    }

  ------静态同步方法

JAVA自学笔记(6)—异常、线程、函数式编程_第23张图片

 

(3)第三种方式 Lock锁

JAVA自学笔记(6)—异常、线程、函数式编程_第24张图片

 

 

写法一:

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 概述

JAVA自学笔记(6)—异常、线程、函数式编程_第25张图片

2.0等待唤醒案例

分析卖包子案例

JAVA自学笔记(6)—异常、线程、函数式编程_第26张图片

 

代码实现

JAVA自学笔记(6)—异常、线程、函数式编程_第27张图片

 

 

 

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方法

JAVA自学笔记(6)—异常、线程、函数式编程_第28张图片

 

JAVA自学笔记(6)—异常、线程、函数式编程_第29张图片

 

 

3.等待唤醒机制

案例

JAVA自学笔记(6)—异常、线程、函数式编程_第30张图片 

 

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+"的包子已经做好 开吃!");
            }
        }

    }
}

 

 

JAVA自学笔记(6)—异常、线程、函数式编程_第31张图片

 

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.线程池

JAVA自学笔记(6)—异常、线程、函数式编程_第32张图片

 

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 概述

JAVA自学笔记(6)—异常、线程、函数式编程_第33张图片

 

2.0体验Lambda的更优

JAVA自学笔记(6)—异常、线程、函数式编程_第34张图片

 

 

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)无参数无返回值

JAVA自学笔记(6)—异常、线程、函数式编程_第35张图片

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可省略

JAVA自学笔记(6)—异常、线程、函数式编程_第36张图片

JAVA自学笔记(6)—异常、线程、函数式编程_第37张图片

 

你可能感兴趣的:(JAVA自学笔记(6)—异常、线程、函数式编程)