欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

学习记录——进阶版07

程序员文章站 2022-06-28 16:36:03
@学习记录开始学习Java遵从同学的指导,从Java se开始学习黑马的JavaSE零基础入门【】教学目标:  能够描述Java中多线程运行原理  能够使用继承类的方式创建多线程  能够使用实现接口的方式创建多线程  能够说出实现接口方式的好处  能够解释安全问题出现的原因  能够使用同步代码块解决线程安全问题  能够使用同步方法解决线程安全问题  能够说出线程6个状态的名称第一章 线程1.1 多线程原理18-02 多线程原理-随机性打印结果......

@学习记录

开始学习Java

遵从同学的指导,从Java se开始学习

黑马的JavaSE零基础入门【线程池、Lambda表达式】

第一章 等待唤醒机制

1.1 线程间通信

1.2 等待唤醒机制

18-03 等待唤醒机制概述

学习记录——进阶版07

18-04 等待唤醒机制需求分析

学习记录——进阶版07

1.3 生产者与消费者问题

18-05 等待唤醒机制代码实现——包子类和包子铺类
package day_07ThreadAndLambda.demo01WaitAndNotify;

/*
资源类:包子
设置包子的属性
    皮
    馅
    包子的状态:有 ture; 没有 false
 */
public class BaoZi {
    String pi;
    String xian;
    // 设置包子的初始值为false
    boolean state = false;

}

package day_07ThreadAndLambda.demo01WaitAndNotify;

/*
生产者(包子铺)类:是一个线程类,可以继承Thread
设置线程任务:生产包子
对包子的状态进行判断
true:有包子
    包子铺调用wait方法进入等待状态
false:没有包子
    包子铺生产包子
    包子铺生产好了包子
    修改包子的状态为true
    唤醒吃货线程,让他吃包子

注意:
    包子铺线程和包子线程的关系 --> 通信(互斥),必须使用同步技术保证量的线程只有一个在执行
    锁对象必须保证唯一,可以使用包子对象作为锁对象
    包子铺类和吃货的类需要把包子对象作为参数传递进来:
        1.需要在成员变量位置创建一个包子类
        2.使用带参数构造方法,为这个包子变量赋值
 */
public class BaoZiPu extends Thread{
    // 1.需要在成员变量位置创建一个包子类
    private BaoZi baoZi;
    // 2.使用带参数构造方法,为这个包子变量赋值
    public BaoZiPu(BaoZi baoZi) {
        this.baoZi = baoZi;
    }
    // 重写线程任务,生产包子
    @Override
    public void run() {
        int count = 0;
        // 使用同步技术保证量的线程只有一个在执行
        synchronized (baoZi) {
            // 对包子的状态进行判断
            if (baoZi.state == true) {
                // 包子铺调用wait方法进入等待状态
                try {
                    baoZi.wait(); // 必须使用锁对象调用wait方法
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println("包子铺正在生产");
            // 生产两种包子
            if (count % 2 == 0) {
                baoZi.pi = "老窖";
                baoZi.xian = "三鲜";
            } else {
                baoZi.pi = "发面";
                baoZi.xian = "荠菜";
            }

            // 包子铺生产包子
            try {
                Thread.sleep(1000);
                System.out.println("包子铺生产好包子");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 修改包子的状态为true
            baoZi.state = true;
            // 唤醒吃货线程,让他吃包子
            baoZi.notify();
            System.out.println("包子已经生产好,吃货可以开吃了");


        }
    }
}


18-06 等待唤醒机制代码实现——吃货类和测试类
package day_07ThreadAndLambda.demo01WaitAndNotify;

/*
消费者(吃货)类是一个线程类,可以继承Thread
设置线程任务:吃包子
对包子的状态进行判断
false:没有包子
    吃货调用wait方法进入等待状态
true:有包子
    吃货吃包子
    吃货吃完包子
    修改包子的状态为false
    吃货唤醒包子铺线程,生产包子
 */
public class ChiHuo extends Thread{
    // 1.需要在成员变量位置创建一个包子类
    private BaoZi baoZi;

    // 2.使用带参数构造方法,为这个包子变量赋值
    public ChiHuo(BaoZi baoZi) {
        this.baoZi = baoZi;
    }

    // 设置线程任务:吃包子
    @Override
    public void run() {
        // 使用同步技术保证量的线程只有一个在执行
        synchronized (baoZi) {
            if (baoZi.state == false) {
                // 吃货调用wait方法进入等待状态
                try {
                    baoZi.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 线程被唤醒之后执行的代码:吃包子
            System.out.println("吃货吃包子:" + baoZi.pi + baoZi.xian);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("吃货吃完包子");
            // 修改包子的状态为false
            baoZi.state = false;
            // 吃货唤醒包子铺线程,生产包子
            baoZi.notify();
            System.out.println("包子铺需要开始生产包子");
            System.out.println("======================");
        }
    }
}

package day_07ThreadAndLambda.demo01WaitAndNotify;

/*
测试类:
包含main方法,程序执行的入口,启动程序
创建包子类对象
创建包子铺线程,开启,生产包子
创建吃货线程,开启,吃包子
 */
public class Demo {
    public static void main(String[] args) {
        // 创建包子类对象
        BaoZi baoZi = new BaoZi();
        // 创建包子铺线程,开启,生产包子
        new BaoZiPu(baoZi).start();
        // 创建吃货线程,开启,吃包子
        new ChiHuo(baoZi).start();
    }
}


第二章 线程池

2.1 线程池思想概述

2.2 线程池概念

18-07 线程池的概念和原理

学习记录——进阶版07
学习记录——进阶版07
学习记录——进阶版07

2.3 线程池的使用

18-08 线程池的代码实现
package day_07ThreadAndLambda.demo02ThreadPool;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
线程池:JDK1.5之后提供的
java.util.concurrent.Executors:线程池的工厂类,用来生成线程池
Executors类中的静态方法:
    static ExecutorService newFixedThreadPool(int nThreads) 创建一个可重复利用固定线程数的线程池
    参数:nThreads 创建线程池中包含的线程数量
    返回值:ExecutorService接口,返回的式ExecutorService接口的实现类对象,可以使用ExecutorService接口接收(面向接口编程)

java.util.concurrent.ExecutorService线程池接口
    用来从线程池中获取线程,调用start方法,执行线程任务
        submit(Runnable task) 提交一个Runnable任务用于执行
    关闭/销毁线程池的方法
        void shutdown()

线程池的使用步骤:
1.使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool创建一个指定线程数量的线程池
2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
4.调用ExecutorService中的方法shutdown销毁线程池(不建议执行)

 */
public class Demo01ThreadPool {
    public static void main(String[] args) {
        // 1.使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool创建一个指定线程数量的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
        executorService.submit(new RunnableImpl());
        executorService.submit(new RunnableImpl());
        executorService.submit(new RunnableImpl());

        // 4.调用ExecutorService中的方法shutdown销毁线程池(不建议执行)
        executorService.shutdown();
    }
}

package day_07ThreadAndLambda.demo02ThreadPool;

// 2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
public class RunnableImpl implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}


第三章 Lambda表达式

3.1 函数式编程思想概述

18-09 函数式编程思想概述

学习记录——进阶版07

3.2 冗余的Runnable代码

传统写法
代码分析

18-10 冗余的Runnable代码
package day_07ThreadAndLambda.demo03Lambda;

/*
创建Runnable接口的实现类,重写run方法,设置线程任务
 */
public class RunnableImpl implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

package day_07ThreadAndLambda.demo03Lambda;

/*
使用实现Runnable接口的方式实现多线程程序
 */
public class Demo01Runnable {
    public static void main(String[] args) {
        // 创建Runnable接口的实现类对象
        RunnableImpl runnable = new RunnableImpl();
        // 创建Thread类对象,构造方法中传递Runnable接口的实现类
        Thread thread = new Thread(runnable);
        // 调用start方法开启新线程,执行run方法
        thread.start();

        // 简化代码,使用匿名内部类实现多线程程序
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();
    }
}

学习记录——进阶版07

3.3 编程思想转换

做什么,而不是怎么做
生活举例

3.4 体验Lambda的更优写法

18-11 编程思想转换以及体验Lambda的更优写法
package day_07ThreadAndLambda.demo03Lambda;

public class Demo02Lambda {
    public static void main(String[] args) {
        // 使用匿名内部类的方式实现多线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        // 使用Lambda表达式实现多线程
        new Thread(()->{
            System.out.println(Thread.currentThread().getName());
        }
        ).start();
    }
}


3.5 回顾匿名内部类

使用实现类
使用匿名内部类
匿名内部类的好处与弊端
语义分析
学习记录——进阶版07
学习记录——进阶版07

3.6 Lambda标准格式

18-12 Lambda标准格式
/*
Lambda表达式的标准格式:
由三部分组成:一些参数,一个箭头,一段代码
格式:(参数列表)-> {一些重写方法的代码}

 */

3.7 练习:使用Lambda标准格式(无参无返回)

题目
解答

18-13 Lambda标准格式(无参无返回)练习
package day_07ThreadAndLambda.demo04Lambda;

/*
需求:
给定一个厨子Cook接口,内含唯一的抽象方法makeFood,且无参无返回
使用Lambda的标准格式调用invokeCook方法,打印输出”吃饭啦“字样
 */
public class Demo01Cook {
    public static void main(String[] args) {
        // 调用invokeCook方法,参数是Cook接口,传递Cook接口的匿名内部类对象
        invokeCook(new Cook() {
            @Override
            public void makeFood() {
                System.out.println("吃饭啦");
            }
        });

        // 使用Lambda标准格式,简化程序
        invokeCook(() -> {
            System.out.println("吃饭啦!");
        });
    }

    // 调用一个方法,参数传递Cook接口,方法内部调用Cook接口中的方法makeFood
    public static void invokeCook(Cook cook) {
        cook.makeFood();
    }
}

package day_07ThreadAndLambda.demo04Lambda;

/*
给定一个厨子Cook接口,内含唯一的抽象方法makeFood,且无参无返回
 */
public interface Cook {
    public abstract void makeFood();
}


3.8 Lambda的参数和返回值

传统写法
代码分析
Lambda写法

18-14 Lambda标准格式(有参有返回)练习
package day_07ThreadAndLambda.demo05Lambda;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

/*
需求:
使用数组存储多个Person对象
对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
 */
public class Demo01Arrays {
    public static void main(String[] args) {
        // 创建数组存储多个Person对象
        Person[] list = {
                new Person("法外",20),
                new Person("狂徒",18),
                new Person("张三",22)
        };


        // 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序(前边-后边)排序
       /* Arrays.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });*/

        // 使用Lambda表达式简化匿名内部类
        Arrays.sort(list, (Person o1, Person o2) ->{
            return o1.getAge() - o2.getAge();

        });

        // 遍历数组
        for (Person person : list) {
            System.out.println(person);
        }
    }
}

package day_07ThreadAndLambda.demo05Lambda;

public class Person {
    private String name;
    private int age;

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

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", 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;
    }
}


3.9 练习:使用Lambda标准格式(有参有返回)

题目
解答

18-15 Lambda标准格式(有参有返回)练习(自定义接口)
package day_07ThreadAndLambda.demo06Lambda;

/*
需求:
给定一个计算器Calculator接口,内涵抽象方法calc可以将两个int数字相加得到和
使用Lambda的标准格式调用invokeCalc方法,完成120和130的相加计算
 */
public class Demo01Calculator {
    public static void main(String[] args) {
        invokeCalc((int a, int b) -> {
            return a + b;
        }, 120, 130);

    }

    public static void invokeCalc(Calculator calculator,int a, int b) {
        int result = calculator.calc(a, b);
        System.out.println(result);
    }
}

package day_07ThreadAndLambda.demo06Lambda;

/*
给定一个计算器Calculator接口,内涵抽象方法calc可以将两个int数字相加得到和
 */
public interface Calculator {
    public abstract int calc(int a, int b);

}

3.10 Lambda省略格式

可推导即可省略
胜率规则

3.11 练习:使用Lambda省略格式

题目
解答

3.12 Lambda的使用前提

18-15 Lambda省略格式和Lambda的使用前提
package day_07ThreadAndLambda.demo03Lambda;

/*
Lambda表达式的标准格式:
由三部分组成:一些参数,一个箭头,一段代码
格式:(参数列表)-> {一些重写方法的代码}

 */
public class Demo02Lambda {
    public static void main(String[] args) {
        // 使用匿名内部类的方式实现多线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        // 使用Lambda表达式实现多线程
        new Thread(()->{
            System.out.println(Thread.currentThread().getName());
        }
        ).start();

        // 优化省略Lambda
        new Thread(()->System.out.println(Thread.currentThread().getName())).start();
    }
}

package day_07ThreadAndLambda.demo04Lambda;

/*
需求:
给定一个厨子Cook接口,内含唯一的抽象方法makeFood,且无参无返回
使用Lambda的标准格式调用invokeCook方法,打印输出”吃饭啦“字样
 */
public class Demo01Cook {
    public static void main(String[] args) {
        // 调用invokeCook方法,参数是Cook接口,传递Cook接口的匿名内部类对象
        invokeCook(new Cook() {
            @Override
            public void makeFood() {
                System.out.println("吃饭啦");
            }
        });

        // 使用Lambda标准格式,简化程序
        invokeCook(() -> {
            System.out.println("吃饭啦!");
        });

        // 优化省略Lambda
        invokeCook(() -> System.out.println("吃饭啦!"));
    }

    // 调用一个方法,参数传递Cook接口,方法内部调用Cook接口中的方法makeFood
    public static void invokeCook(Cook cook) {
        cook.makeFood();
    }
}

package day_07ThreadAndLambda.demo05Lambda;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

/*
需求:
使用数组存储多个Person对象
对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
 */
public class Demo01Arrays {
    public static void main(String[] args) {
        // 创建数组存储多个Person对象
        Person[] list = {
                new Person("法外",20),
                new Person("狂徒",18),
                new Person("张三",22)
        };


        // 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序(前边-后边)排序
       /* Arrays.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });*/

        /*// 使用Lambda表达式简化匿名内部类
        Arrays.sort(list, (Person o1, Person o2) ->{
            return o1.getAge() - o2.getAge();

        });*/

        // 优化省略Lambda
        Arrays.sort(list, (o1, o2) ->o1.getAge() - o2.getAge());

        // 遍历数组
        for (Person person : list) {
            System.out.println(person);
        }
    }
}

package day_07ThreadAndLambda.demo06Lambda;

/*
需求:
给定一个计算器Calculator接口,内涵抽象方法calc可以将两个int数字相加得到和
使用Lambda的标准格式调用invokeCalc方法,完成120和130的相加计算
 */
public class Demo01Calculator {
    public static void main(String[] args) {
        invokeCalc((int a, int b) -> {
            return a + b;
        }, 120, 130);

        // 优化省略Lambda
        invokeCalc((a, b) -> a + b, 120, 130);

    }

    public static void invokeCalc(Calculator calculator,int a, int b) {
        int result = calculator.calc(a, b);
        System.out.println(result);
    }
}

学习记录——进阶版07

本文地址:https://blog.csdn.net/weixin_42690266/article/details/113945128

相关标签: java 多线程