2021年8月19日

今天的内容

1.生产者消费者模式

2.反射

3.单例模式

1.生产者消费者模式【模型】【偏难】

进行线程之间通信使用的。

就是咱们昨天将的wait和notify

RabbitMQ 以后会学第三阶段

消息队列

1.1生活中实际案例的分析

厂家 鸿星尔克

生产者 鸿星尔克的生产厂家

消费者 龙飞

有几个角色?两个一个是生产者,一个消费者

龙飞要去消费,想去购买一双鸿星尔克的鞋。结果鸿星尔克厂家没货,龙飞需要进入到等待状态,鸿星尔克进入生产状态,开始加班加点的生产。生产好以后,告诉消费者(龙飞),来来你可以购买le。

1.2生产者消费者图例

生产者消费者

消费者有两种情况:
1.厂家没货,消费者需要等待(阻塞)
2.厂家有货,消费者直接消费
生产者有两种情况:
1.没货,生产者需要生产
2.有货,进入到阻塞状态

1.3需要解决哪些问题?

1、如何让一个商品成为两个线程的共享资源?

创建一个商品类,在生产者和消费者类下面定义一个成员变量,使用构造方法进行初始化。

2、如果两个线程没有加锁的话,会导致代码的错乱

加锁,对商品进行加锁

写代码的思路:
1.Goods类,线程之间共享的资源
2.生产者类 是一个线程
3.消费者类   是另外一个线程

1
消费者购买了:法拉利,价格为:56.0
3
2
生产者生产了:奥迪A8,价格为:200.0
4
消费者购买了:奥迪A8,价格为:200.0
生产者生产了:保时捷,价格为:300.0
消费者购买了:保时捷,价格为:300.0
生产者生产了:奥迪A8,价格为:200.0
分析执行结果:
打印了1   指向了Productor这个线程里面的else代码 proDuctor这个线程抢到了cpu
goods.wait() Product线程阻塞了,不向下走了
生产者线程阻塞,消费者线程抢到cpu了 Customer这个线程
System.out.println("消费者购买了:" +goods.getName()+",价格为:"+ goods.getPrice()); 消费者购买了:法拉利,价格为:56.0
这个标记是true 没货需要生产。
生产者线程没有抢到cpu,还是消费者抢到了cpu
执行了消费者下面else 唤醒了消费者
会打印3 消费者(Customer)阻塞,生产者(Productor)抢到cpu
会打印2
System.out.println("生产者生产了:"+goods.getName()+ ",价格为:" + goods.getPrice());生产者生产了:奥迪A8,价格为:200.0
唤醒了消费者,
会打印4   消费者抢到cpu 消费者购买了:奥迪A8,价格为:200.0   标记为true
生产者抢到了cpu 打印了生产者生产了:保时捷,价格为:300.0
消费者抢到了cpu 打印了消费者购买了:保时捷,价格为:300.0
生产者抢到了cpu 打印了奥迪A8,价格为:200.0
最后的情况是 凑巧了,生产一个(生产者线程),消费一个(消费者线程交替在执行)

   


要分析执行的结果,我相信,我把这个代码发给大家话,你们的执行的结果和我不一样

但是你必须知道是怎么执行的。你们尝试分析一下这个结果,确实有点难。

我也你不知道是消费者线程先抢到还是生产者线程先抢到?这个是未知数,所以咱们打印的结果是不一样的。

2.反射【重点】

作用:咱们以后会封装一些类,一些方法,等有可能会遇到反射

2.1反射的简单的介绍

java的反射是我们在车哪个系运行的过程中可以动态的获取类的属性,构造方法,方法,父类,接口等内部的信息机制。反射的本质反着来。咱们new一个对象的时候,实际上是由java虚拟机根据Class类对象在运行的时候构建出来的。反射通过Class类对象获取定义的信息(有属性吗,方法,构造方法,等)

换句话说:就是换一种方式获取类对象的属性,方法,父类,接口等。

2.2反射原理的示意图

反射示意图

咱们之前是直接new一个对象出来,然后操作属性,方法等。现在用了反射以后,需要借助于.class文件获取属性和方法。换一种方式获取类对象的属性,方法,父类,接口等。

2.3获取Class对象【.class】

javac这个命令将.java 文件编译成.class文件,name这个.class文件就会包含对类原始定于的信息。属性,方法,构造方法等,。.class文件在运行的时候,会被classLoader加载到咱们的jvm里面。当一个.class文件被加载以后,JVM随即生成一个Class对象

如何创建出来Class对象?有三种方式

1.static Class forName(String name);

静态方法,通过class的调用,传入的参数是一个完整的类名(包名+类名)。

获取到了所对应的Class对象

2.Class 类名.class

通过类名获取Class对象

3.Class 类对象.getClass();

获取class对象

package com.qfedu.b_reflect;

//1.获取Class对象
public class Demo2 {

public static void main(String[] args) throws ClassNotFoundException {
//.class文件的对象
//Person.class文件对象
//Person person = new Person(); 直接获取
//反射 获取的第一种写法  
Class<?> aClass = Class.forName("com.qfedu.b_reflect.Person");
System.out.println(aClass);

//通过类名获取 .class文件对象 第二种写法
Class<Person> class1 = Person.class;
System.out.println(class1);

//通过类对象来获取Class对象
Class<?> class2 = new Person().getClass();
System.out.println(class2);
}
}

2.4获取Constructor类对象【构造方法】

Constructor[] getConstractors();

获取当前类内所有的非私有化的构造方法。

Constructor[] getDeclaredConstructors();

获取当前类下面的所有构造方法

Constructor getConstructor(Class .... initParameterType);

通过构造方方法的参数,获取所对应非私有化构造方法

Constructor getDeclaredConstructor(Class ... initParameterType);

通过传递构造方法的参数,获取对应的额私有化的构造方法

以上的方法都是通过Class对象调用的

以下的方法是通过Constructor对象调用的

Object newInstance(Object .... param);

package com.qfedu.b_reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo3 {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1.先获取Class对象?为什么要先获取CLass类对象?
Class<?> aClass = Class.forName("com.qfedu.b_reflect.Person");
//2.需要使用类对象,获取构造方法
//获取多个公开的构造方法,有两个构造方法
Constructor<?>[] constructors  = aClass.getConstructors();
//System.out.println(constructors);
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);//打印3个
}
System.out.println("===========");
Constructor<?>[]  constructors2 = aClass.getDeclaredConstructors();
for (Constructor<?> constructor : constructors2) {
System.out.println(constructor);//打印3个
}
//能不能获取指定的非私有化的构造方法对象
System.out.println("**************");
//getConstructor这个方法没有传参数,获取的是无参数的构造方法
Constructor<?> constructor = aClass.getConstructor(null);
System.out.println(constructor);
//String.class 获取的是String类的Class对象
//这个构造方法,是带有String参数的构造方法
Constructor<?> constructor1 = aClass.getConstructor(String.class);
System.out.println(constructor1);

Constructor<?> constructor2 = aClass.getConstructor(int.class, String.class);
System.out.println(constructor2);

System.out.println("-----------------");
//相获取私有化的对应构造方法
Constructor<?> constructor3 = aClass.getDeclaredConstructor(int.class);
System.out.println(constructor3);
//构造方法的对象可以获取出来
//构造方法和实例化对象有关系吗?有的
//可以通过构造方法对象来实例化对象,相当于Person person = new Person()
Person person = (Person)constructor.newInstance();//Person person = new Person();
person.setId(1);
person.setName("狗蛋");
System.out.println(person);
Object object = constructor1.newInstance("龙飞");
System.out.println(object);
//私有化的构造方法能不能实例化?也能也不能
//可以加上暴力反射,强行给私有的东西进行赋值
constructor3.setAccessible(true);//得加这个,不然私有化的不能进行赋值
Object object2 = constructor3.newInstance(23);


System.out.println(object2);


}
}

2.5获取Method类对象【成员方法】

Method[] getMethods();

获取当前类下面所有的非私有化的方法,包括从父类继承过来的方法

Method[] getDeclaredMethods();

获取当前类下面的所有的方法,但是不包含从父类继承过来的方法

Method getMethod(String name, Class ...parameters);

获取指定方法,通过方法的参数。

Method getDeclaredMethod(String name, Class ...parameters);

获取当前类私有化的方法

以上的方法都是通过Class对象来调用的

以下方法是通过Method对象来调用的。

Object invoke(Object obj, Object ...... args);【重点!!!重中之重】

调用当前方法

因为咱们以后要封装一些类,这些就是调用方法,可以方法方法执行

invoke这个方法就是让哪个方法对象调用的,就执行哪个方法

package com.qfedu.b_reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo4 {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1.获取class类对象
Class<?> aClass = Class.forName("com.qfedu.b_reflect.Person");
//2.获取Method对象
// Method[] methods = aClass.getMethods();
// for (Method method : methods) {
// //也会打印出来它父类的方法比如wait notify   equals hashCode
// System.out.println(method);
//
// }
//3.获取所有的方法(包含私有化方法),但是不包含父类的方法
// Method[] methods = aClass.getDeclaredMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//4.能不能获取一个方法对象?可以的
//第一个参数就是咱们方法的名字
Method method = aClass.getMethod("test", null);
System.out.println(method);
Method method2 = aClass.getMethod("game", String.class);
System.out.println(method2);//Person类下面的game方法,带有String类型的参数
//5.能不能获取私有化方法
Method method3 = aClass.getDeclaredMethod("test1", null);
System.out.println(method3);

//第一个参数是啥?obj 就是这个method所在的类对象
//方法对象有了, 你得告诉我你这个方法是在哪个对象下面吧。
Object obj = aClass.getConstructor(null).newInstance(null);//Person person= new Person();
//第二个参数是方法的参数
//调用了obj这个对象下面的method方法
//调用了Person这个对象下面的 test方法
method.invoke(obj, null);//invoke 咱们以后必写!!!

method2.invoke(obj, "我来啦");
//能不能调用私有的话成员方法
//能不能暴力反射?可以的
method3.setAccessible(true);
method3.invoke(obj, null);

}
}

2.6获取Field类对象【属性】

Field[] getFields();

获取是非私有化的属性

Field[] getDeclaredFields

获取是全部的属性

Field getField(String name);

获取指定的属性,通过属性的名字。但是只能获取非私有化的

Field getDeclaredField(String name)

通过指定属性的名字,获取私有化的成员属性

以上的方法都是Class类对象调用的

以下的方法是Field对象调用的

set(Object obj, Object value);

package com.qfedu.b_reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
//1.获取CLass类对象
Class<?> aClass = Class.forName("com.qfedu.b_reflect.Person");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
//我想获取私有化的属性
System.out.println("=========");
Field[] fields2 = aClass.getDeclaredFields();//获取全部的属性
for (Field field : fields2) {
System.out.println(field);
}
//能不能获取一个属性?能
System.out.println("************");
Field field = aClass.getField("weight");
System.out.println(field);
//私有化的属性能不能单个获取
Field field2 = aClass.getDeclaredField("id");
System.out.println(field2);
//获取属性对象目的,咱们是不是要对属性进行赋值。
//set(Object obj, Object value);
Person person = (Person)aClass.getConstructor(null).newInstance(null);
//想对哪个属性进行赋值
//filed是weight属性的对象
field.set(person, 34.5);
System.out.println(person);
//对于私有化的话东西进行暴力反射,进行赋值
field2.setAccessible(true);
field2.set(person, 2);
System.out.println(person);



}

}



posted @ 2021-08-19 21:04  张三疯321  阅读(111)  评论(0编辑  收藏  举报