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

转自:头条

作者:java一线架构师

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
        //List<Integer> 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<Integer> 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<Integer> 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<Integer> 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恭喜您,注册成功!

请输入您要注册的姓名:MaryException 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:0Main:1run:0Main:2Main:3run:1Main:4run:2run:3run:4

第二次打印结果:

Main:0run:0Main:1run:1Main:2run:2Main:3run:3Main:4run: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--->0main--->1Thread-0--->0main--->2Thread-0--->1Thread-0--->2main--->3Thread-0--->3main--->4Thread-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<Person>() {
            @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 23V 25Jin 27

4.0 lambda可省略

最后 

今天也给大家带来了独家密的BATJ的面试题和相关学习资料,进大厂就从现在开始吧!想获取这些资料的可以关注小编,转发收藏文章,私信小编【学习】来免费获取吧

BATJ及大厂面试题

JVM系列实战宝典

名厂面试题

坦克大战100集系列—23种设计模式

有了这份面试题,自己梳理好,我不信你进不去大厂,想获取这些资料的可以关注小编,转发收藏文章,私信小编【学习】来免费获取吧!

猜你喜欢

转载自blog.csdn.net/ITjianshuzhai/article/details/106835023