复习
package com.study.a_homework;
/**
* 生产者消费者模式
* @author big God
* @date 2023/1/5 9:46 * @version 1.0
*/
class Pancake {
private String addDishes;
private int price;
private boolean flag;
// flag
// true 有烧饼 生产者等待 消费者被唤醒
// false 没有烧饼 生产者生产 消费者等待
public Pancake() {
}
public Pancake(String addDishes, int price, boolean flag) {
this.addDishes = addDishes;
this.price = price;
this.flag = flag;
}
public String getAddDishes() {
return addDishes;
}
public void setAddDishes(String addDishes) {
this.addDishes = addDishes;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
//生产者一直生产
class BossThread implements Runnable {
private Pancake pancake;
public BossThread(Pancake pancake) {
this.pancake = pancake;
}
@Override
public void run() {
int count = 0;
while (true) {
synchronized (pancake) {
if (!pancake.isFlag()) {
if (count % 2 == 0) {
pancake.setAddDishes("烧饼加牛肉");
pancake.setPrice(10);
} else {
pancake.setAddDishes("烧饼不加菜");
pancake.setPrice(2);
}
pancake.setFlag(true);
System.out.println(Thread.currentThread().getName() + "做了:" + pancake.getAddDishes() + " 价值:" + pancake.getPrice());
count++;
pancake.notifyAll();
} else {
try {
pancake.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
//消费者一直消费
class CustomerThread implements Runnable {
private Pancake pancake;
public CustomerThread(Pancake pancake) {
this.pancake = pancake;
}
@Override
public void run() {
while (true) {
synchronized (pancake) {
if (pancake.isFlag()) {
System.out.println(Thread.currentThread().getName() + "买了:" + pancake.getAddDishes() + " 消费:" + pancake.getPrice());
// 先唤醒生产者再修改 flag
pancake.setFlag(false);
pancake.notify();
} else {
try {
pancake.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Demo2 {
public static void main(String[] args) {
Pancake pancake = new Pancake("烧饼夹豆皮",5,true);
CustomerThread customerThread = new CustomerThread(pancake);
BossThread bossThread = new BossThread(pancake);
new Thread(customerThread,"老张").start();
new Thread(customerThread,"王大娘").start();
new Thread(bossThread,"老板").start();
}
}
package com.study.a_homework;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* ThreadPoolExecutor 手动创建线程池
* @author big God
* @date 2023/1/5 9:39 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
test();
}
private static void test() {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
for (int i = 0; i < 100; i++) {
int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index + "被执行的任务是:" + Thread.currentThread().getName());
}
});
}
}
}
今天的内容
线程池
ThreadPoolExecutor 7 个参数需要理解其中 暂时需要理解五个参数
反射
单例模式
Lambada 表达式
1. 反射
反射 Reflection (反射) 是被视为动态语言的关键,反射机制允许程序在执行期 借助于 ReflectionAPI 取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区中就产生了一个 Class 类型的对象(一个类只有一个 Class 对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
Java 中反射可以动态的获取类,类属性,类方法,类构造方法等一部分的操作!!!
入门案例
package com.study.b_reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author big God
* @date 2023/1/5 12:07 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 创建对象 第一种方式
// 通过构造方法来实例化的一个对象
Person person1 = new Person();
/**
* 借助反射来创建
* Person.class 啥玩意? 一个类会被编译成 .class 文件
* Person.class 这个文件中存的有咱们所有的类的信息(属性,构造方法。成员方法)
* Person.class 这个代码就是将 Person 字节码文件转为了 Class 对象
*
* getConstructor(null) 啥东西?
* 通过 Class 对象获取构造方法对象
* 要构造方法干嘛? 创建对象
*
* newInstance() 啥东西?
* 构造方法对象.newInstance(); 新建实例的意思
*
* 1.获取字节码文件对象
* 2.通过字节码文件对象获取构造方法对象
* 3.通过构造方法对象创建对象
*/
Class<Person> personClass = Person.class; // 获取 Person 类的字节码文件对象
Constructor<Person> constructor = personClass.getConstructor(null);
Person person = constructor.newInstance();
Person person2 = Person.class.getConstructor(null).newInstance();
}
}
1.1 获取 Class 对象
一个类就是 Class 的对象
Java 可以将 .java 文件编译成 .class 文件。那么这个 .claa 文件会变成 Class 对象
.java 中有属性,构造方法,成员方法 => 就意味着 .class 文件中原来 .java 中的所有信息(属性、构造方法、成员方法) => Class 对象中有原始 Java 文件中的所有信息(属性、构造方法、成员方法)
获取一个类的 class 对象有三种方式:
package com.study.b_reflection; /** * @author big God * @date 2023/1/5 12:38 * @version 1.0 */ public class Demo2 { public static void main(String[] args) throws ClassNotFoundException { // 想获取 Person 这个类的字节码文件对象 也就是 Class 对象 /** * 第一种方式:【常用】 * Class.forName(完整的包名.类名); * 第二种方式:【常用】 * 类名.class; * 第三种方式: * 通过对象获取 new Person().getClass; * */ Class<?> aClass = Class.forName("com.study.b_reflection.Person"); System.out.println(aClass); Class<Person> personClass = Person.class; System.out.println(personClass); Class<? extends Person> aClass1 = new Person().getClass(); System.out.println(aClass1); } }
为啥要获取 Class 对象? 因为这个 Class 包含了字节码文件中所有的信息(构造方法、属性、成员方法) 可以通过 Class 对象来获取一个类的构造方法对象、方法对象、属性对象
1.2 获取 Constructor 对象【构造方法对象】
和类中构造方法有关系的,构造方法对象
以上的四个方法是拿谁调用的? Class 对象调用的 Class 对象就是字节码文件,字节码文件中有构造方法,所以只能使用 Class 对象来获取构造方法对象
下面这个方法是使用构造方法调用的
package com.study.b_reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author big God
* @date 2023/1/5 13:50 * @version 1.0
*/
public class Demo3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 我想要获取构造方法对象
// 1.先获取 Class 对象? 为啥要先获取 Class 对象?
// Class 是字节码文件对象,字节码文件里面才有构造方法
Class<Person> personClass = Person.class;
// getConstructor() 获取类下面所有的公开的构造方法
Constructor<?>[] constructors = personClass.getConstructors();
// 碰到数组 遍历
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("================");
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("=============");
// 以上是获取多个的构造方法,能不能获取一个构造方法
// 获取无参构造方法对象
Constructor<Person> constructor = personClass.getConstructor(null);
System.out.println(constructor);
System.out.println("=============");
// 获取有参构造方法对象 public Person(String name, int age) {}
Constructor<Person> constructor1 = personClass.getConstructor(String.class, int.class);
System.out.println(constructor1);
System.out.println("=============");
// 获取私有的构造方法 private Person (String name) {}
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
System.out.println(personClass.getDeclaredConstructor(String.class, int.class));
System.out.println("===============");
// 通过无参构造方法,创建一个对象
Person person = constructor.newInstance();
System.out.println(person);
System.out.println("===============");
// 通过有参构方法对象造创建对象
Person person1 = constructor1.newInstance("张三", 18);
System.out.println(person1);
System.out.println(declaredConstructor.newInstance("李四"));
}
}
一个类(Class 对象) 下面有构造方法(Constructor),有方法(Method),有属性
1.3 获取 Method 方法对象【类中方法】
反射将类中的方法封装成了一个对象 Method method
getMethods 这个方法是通过谁调用出来的?Class 的对象
以上的方法都是 Class 对象调用的
方法对象有了,接下来 方法要被调用。要执行方法
Method 这个类main有一个专门执行方法的
package com.study.b_reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author big God
* @date 2023/1/5 14:31 * @version 1.0
*/
public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> aClass = Class.forName("com.study.b_reflection.Person");
// 获取所有的非私有的方法,公开的方法,父类的公开的方法也会获取
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("============");
// 获取所有的方法,不能获取父类的方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
// 以上获取的都是所有的方法
// 能不能获取某一个方法?
// name 是方法的名字
// parameterTypes 是参数列表 上面方法有没有参数 指定参数类型
System.out.println(aClass.getMethod("eat", null));
Method run = aClass.getMethod("run", String.class);
System.out.println(run);
// 获取私有的 sleep 方法
Method sleep = aClass.getDeclaredMethod("sleep", null);
System.out.println(sleep);
// 想调用 Person 下面的方法
// obj - 第一个参数你得告诉我方法在那个对象下面
// args - 用于方法调用的参数
Object o = aClass.getConstructor(null).newInstance();
run.invoke(o, "张三");
// 获取私有方法需要给予权限
sleep.setAccessible(true);
sleep.invoke(o,null);
}
}
package com.study.c_reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author big God
* @date 2023/1/5 16:17 * @version 1.0
*/
public class Demo3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
Class<Person> personClass = Person.class;
// 获取 Person 类中所有的公开的方法,包含父类的公开的方法
for (Method method : personClass.getMethods()) {
System.out.println(method);
}
System.out.println("=============");
// 获取 Person 类中所有的方法,但不包含父类的方法
for (Method declaredMethod : personClass.getDeclaredMethods()) {
System.out.println(declaredMethod);
}
System.out.println("=============");
/**
* getMethod(String name, Class<?>... parameterTypes)
* 获取公开的方法
* name 方法的名字
* Class<?>... parameterTypes 方法的参数的数据类型 Class 对象
*/
// public void eat () {
Method eat = personClass.getMethod("eat", null);
// public void sleep (String name) {
Method sleep = personClass.getMethod("sleep", String.class);
// public void sleep (String name, char sex) {
Method run = personClass.getMethod("run", String.class,char.class);
// private void fly (String name) { 获取私有化方法
Method fly = personClass.getDeclaredMethod("fly", String.class);
System.out.println(eat);
System.out.println(run);
System.out.println(sleep);
System.out.println(fly);
System.out.println("==============");
/**
* invoke(Object obj, Object... args)
* 第一个参数:你要告知我当前方法在那个对象里面 【注意】
* 第二个参数:方法的参数的实参
*/
Object o = Class.forName("com.study.c_reflection.Person").getConstructor(null).newInstance();
Person person = Person.class.getConstructor(null).newInstance();
eat.invoke(o,null);
sleep.invoke(o,"张三");
run.invoke(person,"李四",'男');
/**
* 调用私有化的方法,出问题吗?
* 出问题了,权限不够咋解决?
* 暴力反射!!!!!!
* 让你操作 fly 方法
*/
fly.setAccessible(true);
fly.invoke(person,"王五");
System.out.println("============");
// 获取私有的构造方法对象 private Person (String name) {
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class);
// 能不能通过私有的构造方法创建对象 ? 不能
// Person person1 = new Person("张三"); 报错!!!
// 私有化的构造方法是不能被实例化的
// 可以通过暴力反射给予权限 使私有化的构造方法可以实例化
declaredConstructor.setAccessible(true);
Person person1 = declaredConstructor.newInstance("张三");
System.out.println(person1);
}
}
1.4 获取 Field 对象【属性对象】
package com.study.c_reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* @author big God
* @date 2023/1/5 17:01 * @version 1.0
*/
public class Demo4 {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取 Class 对象 为啥? 因为我的属性在字节码文件中,字节码文件变成了字节码文件对象 => Class 对象
Class<Person> personClass = Person.class;
// 获取所有的公开的属性对象
for (Field field : personClass.getFields()) {
System.out.println(field);
}
System.out.println("=============");
// 获取所有的属性对象
for (Field declaredField : personClass.getDeclaredFields()) {
System.out.println(declaredField);
}
System.out.println("=============");
/**
* 获取某一个具体的属性对象
* getField(String name); 获取公开的属性
* getDeclaredField(String name); 可以获取所有的属性
*/
Field sex = personClass.getField("sex");
System.out.println(sex);
// 会报错!! 因为getFiled 获取的是公开的属性
// System.out.println(personClass.getField("name"));
Field name = personClass.getDeclaredField("name");
System.out.println(name);
// 属性对象获取出来以后,对属性进行赋值!!!
Person person = personClass.getConstructor(null).newInstance();
/**
* public void set(Object obj,Object value)
*/
sex.set(person,'男');
name.set(person,"张三");
Field age = personClass.getDeclaredField("age");
age.setAccessible(true);
// private 不能使用 set 进行赋值吗? 并不是这样的 暴力反射!!!
age.set(person, 23);
System.out.println(name.get(person));
System.out.println(age.get(person));
System.out.println(sex.get(person));
System.out.println(person);
}
}
2. 单例模式
Java 提供了二十多种设计模式,全球通用,为了更加规范化,重用化,等提供了便捷的方式
才有设计模式
Java 开发中常用设计模式:单例模式 工厂模式 代理模式 策略模式 享元模式 适配器模式 等
单例模式:
要求在程序运行过程中,只出现一个实例化对象。目的是减少内存的开销。【减少空间复杂度】
如何判断是否是同一个对象?
看内存地址,如果内存地址一样,那就绝对是同一个对象。
想一些问题:
创建对象 通过 new 关键字来创建,但是 new 一次 创建一个新的对象,再 new 内存地址肯定不一样
package com.study.d_single;
/**
* @author big God
* @date 2023/1/5 19:10 * @version 1.0
*/
class Person {
private static Person person;
// 私有化构造方法,在外部就不能 new 了, 但是在本类中可以 new
private Person() {}
// 一旦不能 new 这怎么办?
// 弄一个方法 返回 Person 对象 在方法中 new
// 弄成静态的方法 通过类.instance 来调用这个方法
// 静态方法中不能使用非静态的成员变量
public static Person instance () {
// if 语句很重要!!!
if (person == null) {
person = new Person();
}
return person;
}
}
public class Demo1 {
public static void main(String[] args) {
/**
* Person person = new Person();
* Person person1 = new Person();
* // person 和 person1 是否是同一个对象呢? 不是的
* System.out.println(person.hashCode());
* System.out.println(person1.hashCode());
*/
// 在 main 主函数中不能让对象通过 new 出来!!!!
Person instance = Person.instance();
Person instance1 = Person.instance();
Person instance2 = Person.instance();
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}
package com.study.d_single;
/**
* @author big God
* @date 2023/1/6 10:19 * @version 1.0
*/
// 让 dog 对象变成一个单例模式
// 线程安全的写法
class Dog {
// 1. 声明一个静态的成员变量
private static Dog dog;
// 2. 私有化无参构造方法
private Dog () {
}
// 3. 写一个静态的方法 返回的 dog 对象的值
// public static synchronized Dog getInstance() {
public static Dog getInstance() {
/**
* 为什么不能写 this?
* this 代表当前对象
* static 静态方法 没有对象
*/
/**
* dog 还没有 new 呢 会报错
* 报一个空指针异常
*/
// Dog.class 固定写法
synchronized (Dog.class) {
if (dog == null) {
// 非常非常巧,这个两个都没有执行 new Dog() 代码
// 但是都进入到了 dog == null 代码
// 线程 1
// 线程 2 咋解决? 加锁 但是这个锁加在哪合适
dog = new Dog();
}
}
return dog;
}
}
// 以上的单例线程是不是安全的? 不是安全的
// 在线程中获取 dog 对象
// 发现在两个线程中获取 Dog 对象的时候,有可能不一样!!! 那就是线程不安全的问题了
class MyThread1 implements Runnable {
@Override
public void run() {
// 在线程 1 中获取的 dog 对象
Dog dog1 = Dog.getInstance();
System.out.println(dog1);
}
}
class MyThread2 implements Runnable {
@Override
public void run() {
Dog dog1 = Dog.getInstance();
System.out.println(dog1);
}
}
public class Demo2 {
public static void main(String[] args) {
Dog dog1 = Dog.getInstance();
Dog dog2 = Dog.getInstance();
System.out.println(dog1);
System.out.println(dog2);
new Thread(new MyThread1()).start();
new Thread(new MyThread2()).start();
}
}
懒汉式写法
package com.study.d_single;
/**
* @author big God
* @date 2023/1/6 10:44 * @version 1.0
*/
// 懒汉式写法
public class SinglePerson {
// 1. 成员变量
private static SinglePerson singlePerson;
// 2. 私有化构造方法
private SinglePerson () {
}
// 3. 创建一个静态方法,返回 singlePerson 对象
private static synchronized SinglePerson getInstance() {
if (singlePerson == null) {
singlePerson = new SinglePerson();
}
return singlePerson;
}
}
饿汉式写法
package com.study.d_single;
/**
* @author big God
* @date 2023/1/6 10:47 * @version 1.0
*/
// 饿汉式写法
public class SingleDog {
// final 修饰的不能再赋值
private static final SingleDog singleDog = new SingleDog();
private SingleDog () {
}
public static SingleDog getInstance() {
return singleDog;
}
}
懒汉式:线程不安全,但是咱们加了锁,也可以保证线程安全
饿汉式:线程安全的
效率来讲:饿汉的效率高,因为没有锁
内存消耗:饿汉比较消耗内存。
从综合考虑开发使用懒汉式写法!!!
3. Lambda 表达式
JDK 1.8 新特性
Lambda 表达式被称为闭包,又被称为函数式的编程。目的是为了简化代码,但是可读性很差。
3.1 入门案例
package com.study.e_lambda;
/**
* @author big God
* @date 2023/1/6 12:11 * @version 1.0
*/
public class Demo3 {
public static void main(String[] args) {
// Thread 构造方法中 Runnable 这个接口对象
// 当咱们遇到接口对象的时候可以将接口对象的匿名内部类转为 Lambda 表达式
// 注意事项: 要求当前实现接口只能有一个抽象方法
new Thread(() -> {
System.out.println("不知火舞");
}).start();
new Thread(() -> System.out.println("闪电匕首")).start();
new Thread(() -> System.out.println("霸者重装")).start();
}
}
3.2 Lambda 表达式的语法格式
接口式的函数编程,只和接口有关
接口 接口对象名字 = () -> 表达式 这个接口下面的抽象方法是无参无返回值的方法 接口 接口对象名字 = (parameter) -> 表达式 这个接口下面的抽象方法是有参无返回值的方法 接口 接口对象名字 = () -> {表达式;} 这个接口下面的抽象方法是无参有返回值的方法 接口 接口对象名字 = (parameter) -> {表达式;} 这个接口下面的抽象方法是有参有返回值的方法
3.21 接口下面的抽象方法是无参无返回值的方法
package com.study.e_lambda;
/**
* @author big God
* @date 2023/1/6 12:21 * @version 1.0
*/
// 接口,接口下面只有一个抽象方法
interface Computer {
// 无参无返回值的方法
void coding();
}
public class Demo4 {
public static void main(String[] args) {
// 匿名内部类的写法
new Computer() {
@Override
public void coding() {
System.out.println("敲代码");
}
}.coding();
// 使用 Lambda 表达式
// 王氏缩减法
阿毛(() -> System.out.println("框框敲代码"));
// 先写成匿名内部类的写法再缩减即可
// 缩减也不会写,快捷键
((Computer) () -> System.out.println("框框")).coding();
}
// 阿毛 方法是一个接口,可以使用匿名内部类
private static void 阿毛(Computer computer) {
computer.coding();
}
}
3.22 接口下面的抽象方法是有参无返回值的方法
package com.study.e_lambda;
/**
* @author big God
* @date 2023/1/6 12:31 * @version 1.0
*/
// 有参无返回值的方法
interface A {
void eat (String name, int age);
}
public class Demo5 {
public static void main(String[] args) {
// 匿名内部类
test(new A() {
@Override
public void eat(String name, int age) {
System.out.println("姓名:" + name + "年龄:" + age + "在吃饭");
}
},"金蝉",19);
// 快捷键 先写出匿名内部类方式
test((name, age) -> System.out.println("姓名:" + name + "年龄:" + age + "在吃饭"),"金蝉",19);
// 王氏缩减法
test(( name, age) -> System.out.println("姓名:" + name + "年龄:" + age + "在吃饭"),"伽罗",21);
}
public static void test(A a, String name, int age) {
a.eat(name, age);
}
}
3.23 接口下面的抽象方法是无参有返回值的方法
package com.study.e_lambda;
/**
* @author big God
* @date 2023/1/6 13:03 * @version 1.0
*/
interface B {
int num();
}
public class Demo6 {
public static void main(String[] args) {
// 匿名内部类
new B() {
@Override
public int num() {
return 0;
}
}.num();
// Lambda 快捷键
((B) () -> 250).num();
// 王氏缩减法
test(() -> {return 250;});
}
public static void test (B b) {
System.out.println(b.num());
}
}
3.24 接口下面的抽象方法是有参有返回值的方法
package com.study.e_lambda;
/**
* @author big God
* @date 2023/1/6 13:09 * @version 1.0
*/
interface C {
int sum (int a, int b);
}
public class Demo7 {
public static void main(String[] args) {
// 匿名内部类的写法
test(new C() {
@Override
public int sum(int a, int b) {
return a + b;
}
},18, 12);
// Lambda 表达式写法
test((a, b) -> a + b,30,12);
int sum = new C() {
@Override
public int sum(int a, int b) {
return a + b;
}
}.sum(18, 30);
System.out.println(sum);
}
public static void test (C c, int a, int b) {
System.out.println(c.sum(a, b));
}
}
作业:
今天的作业,将今天讲的东西弄懂。
今天晚上写一个总结 这一周讲的东西
明天休息一天
mysql数据安装包,我带着手把手安装!!!
下周六补课!!!