线程池、lambda表达式

01.第一章:线程-等待唤醒机制_线程间通信:

1).“线程间通信”:两个线程是在两个相互隔离的“线程栈”中独立运行;但有些业务需要两个线程来协作完成,这样就需要两个线程有相互协作、配合的能力。
2).两个线程进行协作,就需要相互通信,才能共同完成一个任务。

02.第一章:线程-等待唤醒机制_等待与唤醒机制:

1).“等待与唤醒”就是两个线程进行相互协作的一个体现;
2).例如两个线程工作:
    1).一个线程要生产一些东西;
    2).一个线程要获取那个线程生成的东西;
    很可能会产生一种情况:获取的线程在获取时,生产的线程还没有生产出来东西;获取的线程就
    不能获取到东西,这钟情况在软件运行期间是不允许发生的。如果取不到可以等一会。
    解决方式:
    1).当获取线程去取东西时,发现没有东西,可以“等待”;
    2).当生产的线程生产出来东西时,可以“唤醒”某个、所有等待的线程去取东西。

03.第一章:线程-等待唤醒机制_生产者与消费者的问题:

1).定义“包子铺”:
public class BaoZiPu {
private List baoZiList = new ArrayList<>();

//设置包子
public synchronized void setBaoZi(String s) {
    baoZiList.add(s);
    //让在本对象锁上等待的线程--唤醒
    this.notify();
}

//获取包子
public synchronized String getBaoZi(){
    if (baoZiList.size() == 0) {//没有包子了
        //让持有本对象锁的线程-->等待
        try {
            System.out.println("线程:" + Thread.currentThread().getName() + " 开始等待....");
            this.wait();//释放锁
            System.out.println("线程:" + Thread.currentThread().getName() + " 被唤醒....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    //取包子
    String  s = baoZiList.remove(0);
    System.out.println("线程:" + Thread.currentThread().getName() + " 取走一个:" + s);
    return s;
 }
}
2).“生产者”线程:
public class SetThread extends Thread{
private BaoZiPu bzp ;

public SetThread(BaoZiPu bzp) {
    this.bzp = bzp;
}

@Override
public void run() {
    while (true) {
        bzp.setBaoZi("包子");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  }
}
3).“消费者”线程:
public class GetThread extends Thread {
private BaoZiPu bzp ;

public GetThread(BaoZiPu bzp) {
    this.bzp = bzp;
}

@Override
public void run() {
    while (true) {
        String s = this.bzp.getBaoZi();
        System.out.println(s);
    }
  }
}
4).测试类:
public class Demo {
public static void main(String[] args) {
    //1.创建一个包子铺对象
    BaoZiPu bzp = new BaoZiPu();

    //2.分别创建生产者与消费者线程
    SetThread setThread = new SetThread(bzp);
    GetThread getThread = new GetThread(bzp);

    setThread.start();
    getThread.start();

  }
}

线程池、lambda表达式_第1张图片

04.第二章:线程池_线程池思想概述:

1).什么是“线程池”:就是封装了很多“线程对象”的一个“容器”。
2).为什么要用“线程池”:
    1).一个Thread对象只能执行一次。如果再想执行,必须再次创建对象;而且创建一个Thread对象很耗时,而且很占用内存。
    2).如果一个程序需要反复的、大量的使用同一个线程,就需要反复、大量的创建同一个线程对象,这样就使程序的运行效率降低。
    3).“线程池”可以先期缓存一些“线程对象”,这些线程对象在使用后不会被销毁,如果再次需要,可以再次调用,这样就使得这些“线程对象”可以反复使用,从而提高程序的运行效率。

05.第二章:线程池_线程池概念:

1).Java提供了一个“线程池”的实现;从JDK1.5开始。
2).它可以缓存一些线程对象,并可以反复重用。

06.第二章:线程池_线程池的使用:

public class Demo {
public static void main(String[] args) throws InterruptedException {
    //下面创建了两次对象,每次5秒,一共用时:10秒
    /*MyThread t1 = new MyThread();//需要5秒
    t1.start();
    t1 = new MyThread();//需要5秒
    t1.start();*/
    MyThread t1 = new MyThread();//需要5秒
    //使用线程池--能容纳2个线程的线程池对象
     ExecutorService service = Executors.newFixedThreadPool(2);
    //2.让线程池去执行,并缓存一个线程
     service.submit(t1);//执行,并缓存这个线程;

     System.out.println("主线程休息10秒:" );
    Thread.sleep(1000 * 10);
    System.out.println("主线程醒来,第二次执行开枪线程...");
    service.submit(t1);

    service.submit(t1);
    service.submit(t1);


    //关闭线程池
     service.shutdown();
  }
}

07.第三章:Lambda表达式_回顾面向接口编程及其优点:

public interface IUSB{
    public void run();
}
public class Mouse implements IUSB{
    public void run(){
        System.out.println("鼠标开始工作...");
    }
}
public class Keyboard implements IUSB{
    public void run(){
        System.out.println("键盘开始工作...");
    }

}
public class Computer{
    public void useUsb(IUSB m){//更多设备只需要实现IUSB接口即可,此类就可以不用更改。利于程序的扩展
        m.run();
    }
}
测试类:
main(){
    Computer pc = new Computer();
    pc.useUsb(new Mouse());
    pc.useUsb(new Keyboard());
    //匿名对象
    pc.useUsb(new IUSB(){
        public void run(){
            System.out.println("手机可以插到电脑上了....");
        }
    });
}

08.第三章:Lambda表达式_回顾冗余的Runnable代码:

//2.需要一个线程:打印i
new Thread(new Runnable() {
@Override
public void run() {
    for (int i = 0; i < 100 ; i++) {
        System.out.println("i =  " + i);
    }
}
}).start();

//3.还需要一个线程:打印k
new Thread(new Runnable() {
@Override
public void run() {
    for (int k = 0; k < 100 ; k++) {
        System.out.println("k =  " + k);
    }
}
}).start();

//4.需要一个线程:打印m
new Thread(new Runnable() {
@Override
public void run() {
    for (int m = 0; m < 100 ; m++) {
        System.out.println("m =  " + m);
    }
}
}).start();

09.第三章:Lambda表达式体验Lambda的更优写法示意图:

new Thread(()->{
for (int i = 0; i < 100 ; i++) {
    System.out.println("i =  " + i);
}
}).start();
new Thread(()->{
for (int k = 0; k < 100; k++) {
    System.out.println("k = " + k);

}
}).start();
new Thread(()->{
    for (int m = 0; m < 100; m++) {
        System.out.println("m = " + m);

    }
}).start();
匿名内部类和Lambda表达式的对应关系图:

线程池、lambda表达式_第2张图片

10.第三章:Lambda表达式_编程思想转换及函数式编程思想概述:

1).编程思想的转换:
    之前:要制作多个Runnable的匿名子类。
    现在:只需要关注这些子类中具体要做什么,将要做的事情使用Lambda表达式传递个方法即可。
2).什么是“函数式编程”:
    之前考虑传递的是“匿名子类的对象”。
    现在考虑传递的是“做什么的函数(方法)”。
    将“匿名子类对象”使用“没有名字的函数”来代替。

11.第三章:Lambda表达式Lambda的使用前提标准格式:

1).Lambda的使用前提:
    1).Lambda代替的必须是一个“接口类型”;
    2).接口中有且只有一个抽象方法(形参和返回值都可以有,可以无)
       (接口中可以有默认方法、静态方法等)
2).标准格式:
    1).一个小括号(形参列表)
    2).一个箭头(->)
    3).一段代码:(方法体--带大括号,有时可以不带大括号)

12.第三章:Lambda表达式练习使用Lambda的标准格式(无参无返回值):

1).public interface IAnimal{
        public void eat();
   }
   public class Cat implements IAnimal{
        public void eat(){
            System.out.println("猫吃鱼...");
        }
   }
2).测试类:
    main(){
        public static void main(String[] args){
            //1.自定义子类
            show(new Cat());
            //2.匿名子类
            show(new IAnimal(){
                public void eat(){
                    System.out.println("狗吃骨头...");
                }
            });
            //3.使用Lambda
            show(()->System.out.println("猪吃草..."));
            show(()->System.out.println("羊吃草..."));

        }
        public static void show(IAnimal a){
            a.eat();
        }
    }

13.第三章:Lambda表达式练习使用Lambda的标准格式(有参有返回值):

1).例一:自定义接口:
interface IA{
public int calc(int a, int b);
}
class Zi implements IA{
@Override
public int calc(int a, int b) {
    return a + b;
}
}
public class Demo {
public static void main(String[] args) {
    //1.使用子类
    /*show(new Zi(), 10, 20);
    //2.使用匿名对象
    show(new IA() {
        @Override
        public int calc(int a, int b) {
            return a * b;
        }
    }, 10, 20);*/
    //3.使用Lambda
    //加法
    show((int a, int b) -> {return a + b; }, 10, 20);
    //减法
    show((int a,int b)->{return a - b;},10,20);
    //乘法
    show((int a, int b) -> { return a * b;}, 10, 20);
    //除法
    show((int a,int b)->{return a / b;},10,20);

}

public static void show(IA ia,int x,int y) {
    System.out.println(ia.calc(x,y));
}
}

2).例二:类库的接口:
public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

@Override
public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}
}
public static void main(String[] args) {
ArrayList stuList = new ArrayList<>();

stuList.add(new Student("Jack",19));
stuList.add(new Student("Rose", 18));
stuList.add(new Student("Anna",20));
stuList.add(new Student("Rose",21));
stuList.add(new Student("Rose", 16));

Collections.sort(stuList,(Student o1,Student o2)->{return o1.getAge() - o2.getAge();});

System.out.println(stuList);

}

14.第三章:Lambda表达式练习使用Lambda的标准格式(有参无返回值):

Arrays.sort(T[] arr,Comparator cp)
interface IA{
public void show(int a, int b);
}
public class Demo {
public static void main(String[] args) {
   //匿名内部类:
   fun(new IA(){
    public void show(int m,int n){
        System.out.println(m + n);
    },10,20);
   //使用Lambda
    fun((int m,int n)->{System.out.println(m + n);},10,20);
    fun((int m,int n)->{System.out.println(m * n);},10,20);   
}

public static void fun(IA a, int x, int y) {
    a.show(x,y);
}
}

15.第三章:Lambda表达式_Lambda的省略格式及省略原则:

1).省略原则:
    1).Lambda中形参列表的“数据类型”都可以省略(要省全省,否则全不省);
    2).如果形参只有一个,数据类型和小括号可以省略(要省略小括号,必须省略数据类型);
    3).如果大括号(方法体)只有一句话,
       可以省略:return关键字、大括号、语句后的分号(要省就全省,要用就全用)
       例如:有返回值:可以省略return、大括号、语句后的分号
       Collections.sort(stuList,(o1,o2)->{return o1.getAge()-o2.getAge();});//完整语句
       Collections.sort(stuList,(o1,o2)-> o1.getAge()-o2.getAge());//省略语句
       例如:无返回值:可以省略:大括号、语句后的分号;
       interface IAnimal{
        public void eat();
       }
       public static void main(String[] args){
        show(()->{System.out.println("猫吃鱼...");});//完整格式;
        show(()->System.out.println("猫吃鱼..."));//省略格式
       }
       public static void show(IAnimal a){
        a.eat();
       }

总结:
01.能够理解线程通信概念
1).指多个线程共同完成一个任务的过程中,需要相互传递信息,相互协同,从而完整的完成同一个任务,这就需要线程间进行通信;
02.能够理解等待唤醒机制
1).等待和唤醒机制是线程间通信的一种形式;一个线程等待,另一个线程唤醒之前等待的线程;这就体现了两个线程在协作;
03.能够描述Java中线程池运行原理
1).就是缓存了大量“线程对象”的一个“容器”。容器中的“线程对象”都可以反复重用,从而提高程序的执行效率。
04.能够理解函数式编程相对于面向对象的优点
1).函数式编程是向方法中传递“一个函数”,不需要定义接口的子类,然后创建子类对象,并传到方法中,函数式编程关注的是:做什么,而不是以什么形式做,所以代码上看起来更简洁。
05.能够掌握Lambda表达式的标准格式
1).一对小括号;
2).一个箭头;
3).一对大括号(方法体)
06.能够使用Lambda标准格式使用Runnable与Comparator接口
1.Runnable:
new Thread(()->{System.out.println(“线程启动…”);}).start();
2.Comparator:

Collections.sort(stuList,(Student o1,Student o2)->{return o1.getAge()-o2.getAge();});

07.能够掌握Lambda表达式的省略格式与规则
1).形参类型都可以省略;
2).如果只有一个形参:可以省略:小括号和形参类型;
3).如果后面的大括号中只有一句代码:
有返回值的情况:可以省略:return、大括号、语句后的分号;
无返回值的情况:可以省略:大括号、语句分号;
08.能够使用Lambda省略格式使用Runnable与Comparator接口
1.Runnable:
new Thread(()->System.out.println(“线程启动…”)).start();
2.Comparator:

Collections.sort(stuList,(o1,o2)->o1.getAge()-o2.getAge());

09.能够通过Lambda的标准格式使用自定义的接口(有且仅有一个抽象方法)
interface IA{
public void show();
}
public static void main(String[] args){
fun(()->{System.out.println(“呵呵”);});
}
public static void fun(IA a){
a.show();
}
10.能够通过Lambda的省略格式使用自定义的接口(有且仅有一个抽象方法)
fun(()->System.out.println(“呵呵”));

11.能够明确Lambda的两项使用前提
1).必须是一个接口类型;
2).接口中必须只有一个抽象方法;(抽象方法必须能够上下文推断)

你可能感兴趣的:(线程池、lambda表达式)