JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)

01.第一章:线程池_概念及作用:

1).什么是“线程池”:指封装了很多的“线程对象”的一个容器。

2).作用:内部的这些线程对象可以被“重复使用”;
线程对象每次使用完成后,会自动成为垃圾,不能再次的start。如果想要再次使用就需要再创建一个线程对象,但创建一个线程对象需要很大的系统开销,所以如果需要大量的、反复的执行同一线程会降低程序的效率。所以提出了“线程池”的概念。

02.第一章:线程池_示例:

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第1张图片

public class Demo {
    public static void main(String[] args) {
        /*MyThread t1 = new MyThread();//需要5秒
        t1.start();//鼓掌...

        //过一会,还需要鼓掌的线程
        t1 = new MyThread();//需要5秒
        t1.start();//再次鼓掌....*/

        //使用线程池;
        //1.获取一个线程池对象;
        ExecutorService service = Executors.newFixedThreadPool(20);//表示创建一个可以容纳2个核心的线程的"线程池"对象
        //2.让线程池去执行,并缓存一个线程对象
        MyThread t = new MyThread();//需要5秒
        service.submit(t);//被第一次执行...
        //3.重复执行之前的线程
        System.out.println("再次执行鼓掌线程.....");
        service.submit(t);//被第二次执行
    }
}

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第2张图片

03.第一章:线程池_实现线程的方式三_Callable接口:

1).之前我们学了两种实现线程的方式:

1).继承自Thread,重写run()
2).实现Runnable接口,重写run()
注意:上面两种方式都是run(),而这个run()方法有个缺点:不能返回值
如果我们希望“线程中”为主线程返回一些数据,之前的两种方式是做不到的。

2).从JDK5开始,又提供了实现线程的第三种方式:实现Callable接口,重写call()方法(相当于run()).

但这个方法可以返回值。 注意:Callable接口的方式实现线程,需要“线程池”来运行;

3).Callable接口与之前的两种方式的重要区别:Callable接口的方式可以返回值
3).示例代码:

/*
    制作一个线程,这个计算1--100的累加和,并将结果返回给主线程
*/

public class MyCallable implements Callable {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100 ; i++) {
            sum += i;

        }
        return sum;
    }
}
		测试类:
public class Demo {
    public static void main(String[] args) 
				throws ExecutionException, InterruptedException {
        //1.创建一个线程池对象
        ExecutorService service = Executors.newFixedThreadPool(2);

        //2.创建MyCallable对象
        MyCallable myCall = new MyCallable();
        //3.让线程池去执行这个线程
        Future future = service.submit(myCall);

        Integer result = future.get();//获取结果
        System.out.println("主线程收到的结果是:" + result);
    }
}

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第3张图片

04.第二章:Lambda表达式_示例:

1).示例代码:

	1).定义一个接口:
	
public interface Animal {
    public void eat();
}

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第4张图片

05.第二章:Lambda表达式_函数式编程思想_相对于面向对象的优点:

1).面向对象的方式:定义类,并创建对象,传递实参,调用方法;
2).Lambda:不需要制作类,不需要创建对象,直接传递一个“方法”作为实参;
可以节省代码的编写。

06.第二章:Lambda表达式_Lambda的标准格式【重点掌握】:

	fun(()->{
		System.out.println("小猪吃草...");
		}
	);

1).一对小括号:表示形参
2).一个右箭头:->
3).一对大括号:方法体
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第5张图片

07.第二章:Lambda表达式_Lambda的前提条件

1).必须要有一个“接口”;
2).接口中有、且只有一个“抽象方法”(可以定义参数、返回值) 这是函数式接口

1).必须有、且只有一个抽象方法;
2).其它静态方法、默认方法有没有、有多少都无所谓

3).Lambda几种常见的形式:
//1.作为形参:
public static void main(String[] args) {
//1.调用方法,传递实参时–前提:方法的形参必须是:接口,而且里面有,且只有一个抽象方法
fun(()->{
System.out.println(“小猪吃草…”);
});

//2.声明变量:

Animal a = ()-> {
            System.out.println("小猪吃草...");
            };

//3.作为返回值

  Animal animal = getAnimal();
    animal.eat();
}
public static void fun(Animal a){
    a.eat();
}

public static Animal getAnimal(){
    /*return new Animal() {
        @Override
        public void eat() {
            System.out.println("小猪吃草...");
        }
    };*/
    return () ->{
        System.out.println("小猪吃草...");
    };
}

08.第二章:Lambda表达式_Lambda的标准格式_参数和返回值:

//1.定义一个接口,接口中抽象方法是:带参、带返回值

   public interface MyMath {
        public int calc(int a,int b);
    }

//2.调用
public class Demo {
public static void main(String[] args) {
//1.匿名内部类

fun(new MyMath() {
    @Override
    public int calc(int a, int b) {
        return a + b;
    }
    },10,20);

//2.使用Lambda–由于接口中的方法是带参、带返回值的,所以导致Lambda也要带参,带返回值

       fun((int a, int b)-> {
            return a * b;
        },10,20);

    }

    public static void fun(MyMath myMath,int m,int n) {
        int r = myMath.calc(m,n);
        System.out.println("结果是:" + r);
    }
}

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第6张图片

09.第二章:Lambda表达式_Lambda的省略格式及省略规则

1).关于Lambda表达式的参数:
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第7张图片

1).形参的“数据类型”都可以省略 fun((a, b)-> {
return a * b;
},10,20);

2).如果只有一个形参,可以同时省略:数据类型,一对小括号;
(如果省略小括号,必须省略数据类型)

1).定义一个接口:

    public interface MyMath2 {
        public void calc(int a);
    }
2).测试类:
			
    public class Demo {
        public static void main(String[] args) {
            fun( a ->{//形参只有一个,可以同时省略:小括号和数据类型
                System.out.println(a);
            },10);
        }
        public static void fun(MyMath2 myMath2,int m){
            myMath2.calc(m);
        }
    }

2).关于Lambda表达式的方法体:
1).如果方法体中只有一句话:可以同时省略:一对大括号,return关键字,这条语句后面的分号
要省全省,要用全用
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第8张图片

示例一:

1).定义一个接口:
		
public interface MyMath2 {
    public void calc(int a);
}

2).测试类:

public class Demo {
    public static void main(String[] args) {
        fun( a ->//形参只有一个,可以同时省略:小括号和数据类型
            System.out.println(a)//可以同时省略:大括号,语句后的分号
        ,10);
    }
    public static void fun(MyMath2 myMath2,int m){
        myMath2.calc(m);
    }
}

示例二:有参,有返回值:

1).定义一个接口:			
    public interface MyMath2 {
        public int calc(int a,int b);
    }

2).测试类:

public class Demo {
    public static void main(String[] args) {
	  //完整格式
        fun( (int a,int b) ->{
            return a + b;
		},10,20);
	  //省略格式
	  fun((a,b) -> a + b,10,20);

    }
    public static void fun(MyMath2 myMath2,int m,int n){
        int r = myMath2.calc(m,n);
	   System.out.println(r);
    }
}
	-------------------------------------------------------------
	
	小结省略规则:
	1).形参:数据类型可以省略
	2).形参:如果只有一个形参,可以同时省略:小括号,数据类型;
	3).方法体:如果只有一句话,可以同时省略:大括号,return关键字,词条语句后的分号。

10.第三章:接口在类库架构中的作用:

1).解开类和类之间的耦合

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第9张图片
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第10张图片
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第11张图片
JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第12张图片

11.第三章:函数式接口_概述

1).有,且只有一个抽象方法的接口,叫:函数式接口;
2).通常为了使用Lambda表达式,所以经常会特意的定义一些“函数式接口”。
3).为了避免定义函数式接口错误,Java为我们提供了一个“注解”,它类似于"@Override"注解,给编译器看的,
	   让编译器为我们检查这个接口是否是一个合格的函数式接口。
	   注解名:@FactionalInterface
4).示例代码:
@FunctionalInterface//作用:保证我们定义的接口是一个合格的函数式接口
public interface Animal {
    public void eat();
   
}

12.第三章:函数式接口_Supplier接口(生产者接口)

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第13张图片
1).函数式接口原型:
T get()
2).示例代码:

public class Demo {
public static void main(String[] args) {
        //1.使用匿名子类对象
	fun(new Supplier() {
    		@Override
   		 public String get() {
        		return "HelloWorld!";
    		}
	});
``
	//2.使用Lambda
	fun(()->{return "HelloWorld!";});

   }
   //下面的方法预先定义好的
     //此方法需要一个Supplier的子类对象,为fun()返回一个String对象
    public static void fun(Supplier s){
	 String s = s.get();
	 System.out.println(s);

   }
}

13.第三章:函数式接口_Consumer接口(消费者接口)

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第14张图片
1).抽象方法原型:
void accept(T t);
示例代码:

public class Demo {
    public static void main(String[] args) {
        //1.使用匿名内部类调用
        
    fun(new Consumer() {
        @Override
        public void accept(String s) {
            System.out.println("转换为大写输出:" + s.toUpperCase());
        }
    },"Hello");

       //2.使用Lambda表达式
 

           fun(t -> System.out.println("转换为小写:" + t.toLowerCase()), "Hello");
        }
        //此方法需要一个Consumer和一个String
        //此方法内部会将String传给Consumer,子类决定做什么
        public static void fun(Consumer c,String s){
            c.accept(s);
        }
    }

2).默认方法:
andThen()
作用:当需要连续的两次处理同一数据时,可以使用这个方法
示例代码:

public class Demo {
    public static void main(String[] args) {
        fun(s-> System.out.println("转换为大写:" + s.toUpperCase()),
                s -> System.out.println("转换为小写:" + s.toLowerCase()),
                "HelloWorld");

    }
        //andThen
    public static void fun(Consumer c1,Consumer c2,String str){
        //先调用c1.accept()然后再调用c2.accept()
       /* c1.accept(str);
        c2.accept(str);
*/
       //等同于上面的写法
       c1.andThen(c2).accept(str);//内部就是先调用c1.accept()然后再调用c2.accept()
    }
}

14.第三章:函数式接口_Function接口(函数)

1).抽象方法原型:
R apply(T t):接收第一个泛型类型,返回第二个泛型类型
通常是用于做“转换”。

2).默认方法:
andThen:当需要将一个数据进行两次连续的转换时,可以使用此方法。
示例代码:

public class Demo {
    public static void main(String[] args) {
        fun(s -> Integer.parseInt(s) + 10,n -> Integer.toString(n),"25");
    }
    
    //andThen:将一个String转换为Integer,然后 + 10 ,然后再转换为String
    public static void fun(Function f1,Function f2,String age){
        /*Integer intAge = f1.apply(age);
        String str = f2.apply(intAge);*/
        String str = f1.andThen(f2).apply(age);
        System.out.println("字符串的结果:" + str);
    }
}

15.第三章:函数式接口_Predicate接口(判断接口)

JAVA进阶知识点总结 7-线程池、Lambda、函数式接口(生产者接口,消费者接口,函数接口,判断接口)_第15张图片
1).抽象方法原型:

	boolean test(T t);
	    示例代码:
public class Demo {
    public static void main(String[] args) {
    //1.匿名内部类
    
fun(new Predicate() {
    @Override
    public boolean test(String s) {
        return s.length() >= 5;
    }
}, "Hell");

//2.使用Lambda

        fun(s -> s.length() >= 5,"Hell");
    }

    public static void fun(Predicate p,String s){
        boolean b = p.test(s);
        System.out.println("判断的结果:" + b);
    }
}

2).默认方法:
1).and():可以将两个Predicate的判断做逻辑与的判断;

public class Demo {
    public static void main(String[] args) {
        //验证一个字符串是否即包含大写的H,又包含大写的W
        fun(s->s.contains("H"),s-> s.contains("W"),"HelloWorld");
    }  


//定义一个方法,可以对一个字符串进行两个判断,可以打印:两个判断的"并且"的结果

    public static void fun(Predicate p1,Predicate p2,String s){
        /*boolean b1 = p1.test(s);
        boolean b2 = p2.test(s);
        System.out.println(b1 && b2);*/
        
    //等同于上面的效果
        boolean b2 = p1.and(p2).test(s);
    }
}

2).or():可以将两个Predicate的判断做逻辑或的判断;
3).negate():将一个Predicate的判断“取反”:

学习目标总结:

01.能够描述Java中线程池运行原理
1).可以缓存多个“线程对象”,并且可以将这些“线程对象”进行“重用”,这样可以大大降低创建线程对象的次数,提高程序的运行效率。
02.能够理解函数式编程相对于面向对象的优点
1).不用定义类,不用创建对象,直接传递方法体;代码简洁
03.能够掌握Lambda表达式的标准格式
1).一个小括号:形参
2).一个右箭头:语法
3).一对大括号:方法体
04.能够掌握Lambda表达式的省略格式与规则
省略规则:
1).形参:形参类型都可以省略;
2).形参:如果只有一个形参,可以同时省略:小括号,数据类型;
3).方法体:如果方法体中只有一句话,可以同时省略:大括号,return,分号。
05.能够明确Lambda的两项使用前提
1).必须是接口;
2).必须是“函数式接口”–有,且只有一个抽象方法。
06.能够使用Supplier函数式接口
1).生产者接口:没有参数,只有返回值
2).
public static void main(String[] args) {
//1.使用匿名子类对象
fun(new Supplier() {
@Override
public String get() {
return “HelloWorld!”;
}
});
//2.使用Lambda
fun(()->{return “HelloWorld!”;});
}

public static void fun(Supplier s){
String str = s.get();
System.out.println(str);
}

07.能够使用Consumer函数式接口
1).消费者接口:只有参数,没有返回值
public static void main(String[] args) {
//1.使用匿名内部类调用
fun(new Consumer() {
@Override
public void accept(String s) {
System.out.println(“转换为大写输出:” + s.toUpperCase());
}
},“Hello”);

    //2.使用Lambda表达式
    fun(t -> System.out.println("转换为小写:" + t.toLowerCase()), "Hello");
    
}
//此方法需要一个Consumer和一个String
//此方法内部会将String传给Consumer,子类决定做什么
public static void fun(Consumer c,String s){
    c.accept(s);
}

08.能够使用Function函数式接口
1).函数接口:有入、有出
public class Demo {
public static void main(String[] args) {
//1.使用匿名内部类
fun(new Function() {
@Override
public String apply(Integer value) {
return value.toString();
}
},25);

    //2.使用Lambda
    fun(a -> a.toString(),25);
}
//此方法需要一个具有Integer和String泛型的Function子类对象
//方法内部调用Function子类的apply,接收一个Integer,返回一个String

public static void fun(Function fun,int age){
    String s = fun.apply(age);
    System.out.println("字符串的值:" + s);

}

}

09.能够使用Predicate函数式接口
1).判断接口:接收一个数据,返回一个boolean
public static void main(String[] args) {
//1.匿名内部类
fun(new Predicate() {
@Override
public boolean test(String s) {
return s.length() >= 5;
}
}, “Hell”);

//2.使用Lambda
fun(s -> s.length() >= 5,"Hell");

}

public static void fun(Predicate p,String s){
boolean b = p.test(s);
System.out.println(“判断的结果:” + b);

}

你可能感兴趣的:(java基础知识点)