Java小白学点东西(17)

本文介绍了Java并发编程中的生产者消费者模式,通过实例解释了线程间通信的wait和notify方法应用。同时,文章探讨了反射机制,阐述了反射在运行时获取类信息、构造方法、成员方法及属性的操作,并提供了相关示例代码。

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

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

就是咱们昨天将的wait和notify的运用

1.1生活中实际案例的分析

厂家 鸿星尔克

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

消费者 张三

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

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

1.2生产者消费者图例

 

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

1.3需要解决哪些问题?

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

享资源?

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

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

加锁,对商品进行加锁

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

public class Shoose {
    private String name;
    private double price;
    private boolean isShoose;
    public Shoose(boolean isShoose){
        this.isShoose=isShoose;
    }
    public Shoose(String name, double price, boolean isShoose) {
        this.name = name;
        this.price = price;
        this.isShoose = isShoose;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public boolean isShoose() {
        return isShoose;
    }

    public void setShoose(boolean shoose) {
        isShoose = shoose;
    }
}
public class Productor implements Runnable{
    private Shoose shoose;

    public Productor(Shoose shoose) {
        this.shoose = shoose;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        int count = 0;
        while (true){
            synchronized (shoose){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (shoose.isShoose()){
                    //仓库为空 需要生产
                    if (count%2==0){
                        shoose.setName("鸿星尔克A");
                        shoose.setPrice(300.00);
                    }else {
                        shoose.setName("鸿星尔克B");
                        shoose.setPrice(500.00);
                    }
                    System.out.println(name+"生产了:"+shoose.getName()+",价格为:"+shoose.getPrice()+"元");
                    //生产过后 仓库有货 需要消费者进行购买
                    shoose.setShoose(false);
                    count++;
                    shoose.notify();
                }else {
                    //不需要生产 进入阻塞状态
                    try {
                        shoose.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
public class Customer implements Runnable{
    private Shoose shoose;

    public Customer(Shoose shoose) {
        this.shoose = shoose;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        while (true){
            synchronized (shoose){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (!shoose.isShoose()){
                    //需要购买
                    System.out.println(name+"购买了:"+shoose.getName()+",花了:"+shoose.getPrice()+"元");
                    shoose.setShoose(true);
                    //唤醒生产者
                    shoose.notify();
                }else {
                    //没货购买 需要等待
                    try {
                        shoose.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
public class Client {
    public static void main(String[] args) {
        Shoose shoose = new Shoose(true);
        Productor productor = new Productor(shoose);
        Customer customer = new Customer(shoose);
        Thread thread1 = new Thread(productor,"鸿星尔克厂家");
        Thread thread2 = new Thread(customer,"张三");
        thread1.start();
        thread2.start();
    }
}

要分析执行的结果,这里就不详细讲了

 

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

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

2.反射【重点】

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

2.1反射的简单的介绍

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

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

2.2反射原理的示意图

 

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

2.3获取Class对象【.class】

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

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

1.static Class forName(String name);

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

获取到了所对应的Class对象

2.Class 类名.class

通过类名获取Class对象

3.Class 类对象.getClass();

获取class对象

//获取Class对象
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.qwzstu.test.Demo1");//第一种获取方法
        System.out.println(aClass);
        //Class<Demo1> aClass1 = Demo1.class;//第二种获取方法
       // Class<?> aClass2 = new Demo1().getClass();//第三种获取方法

    }
}

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

Constructor[] getConstractors();

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

Constructor[] getDeclaredConstructors();

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

Constructor getConstructor(Class .... initParameterType);

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

Constructor getDeclaredConstructor(Class ... initParameterType);

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

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

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

Object newInstance(Object .... param);

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

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("com.qwzstu.test.Demo1");//第一种获取方法
        Constructor<?>[] constructors = aClass.getConstructors();//获取所有非私有化的构造方法
        for (Constructor constructor:
             constructors) {
            System.out.println(constructor);
        }
        System.out.println("=================================");
        //获取所有的构造方法(包括私有的)
        Constructor<?>[] constructors1 = aClass.getDeclaredConstructors();
        for (Constructor constructor:
             constructors1) {
            System.out.println(constructor);
        }
        System.out.println("====================================");
        //获取指定的构造方法
        //获取无参的构造方法
        Constructor<?> constructor1 = aClass.getConstructor();
        System.out.println(constructor1);
        //获取带 String 和 double 参数的构造方法
        Constructor<?> constructor2 = aClass.getConstructor(double.class,String.class);
        System.out.println(constructor2);
        //获取私有化构造方法
        Constructor<?> constructor3 = aClass.getDeclaredConstructor(int.class);
        System.out.println(constructor3);
        System.out.println("======================================");
        //实例化对象
        Demo1 demo1 =(Demo1)constructor2.newInstance(100.00,"张三");
        demo1.setId(1);
        System.out.println(demo1);
        //结果:Demo1{price=100.0, id=1, name='张三'}

        //使用私有的构造方法
        constructor3.setAccessible(true);
        Demo1 demo2 = (Demo1) constructor3.newInstance(5);
        demo2.setName("赵四");
        demo2.setPrice(500.00);
        System.out.println(demo2);
        //结果:Demo1{price=500.0, id=5, name='赵四'}
    }
}

 

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这个方法就是让哪个方法对象调用的,就执行哪个方法

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

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("com.qwzstu.test.Demo1");
        //获取所有公开的成员方法
        Method[] methods1 = aClass.getMethods();
        for (Method m :
                methods1) {
            System.out.println(m);
        }
        System.out.println("==================================");
        //获取所有的成员方法(包括私有的)
        Method[] methods2 = aClass.getDeclaredMethods();
        for (Method m2 :
                methods2) {
            System.out.println(m2);
        }
        System.out.println("===================================");
        //获得指定的公开的成员方法
            //无参的
            Method method3 = aClass.getMethod("test1");
            System.out.println(method3);
            //有参的
            Method method4 = aClass.getMethod("speak", String.class);
            System.out.println(method4);
        //获得私有的指定的方法
            Method method = aClass.getDeclaredMethod("tell");
            System.out.println(method);
        System.out.println("===============================");
        //调用方法
        Constructor<?> constructor = aClass.getConstructor();
        Demo1 demo1 = (Demo1) constructor.newInstance();
        //无参的成员方法
        method3.invoke(demo1,null);
        //有参的成员方法
        method4.invoke(demo1,"赵四");
        //私有化成员方法
        //暴力反射
        method.setAccessible(true);
        method.invoke(demo1);
    }
}

 

2.6获取Field类对象【属性】

Field[] getFields();

获取是非私有化的属性

Field[] getDeclaredFields

获取是全部的属性

Field getField(String name);

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

Field getDeclaredField(String name)

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

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

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

set(Object obj, Object value);

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

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.qwzstu.test.Demo1");
        //获取全部非私有的属性
        Field[] field = aClass.getFields();
        for (Field field1 :
               field ) {
            System.out.println(field1);
        }
        //获取全部的属性(包括私有的)
        Field[] fields = aClass.getDeclaredFields();
        for (Field f :
                fields) {
            System.out.println(f);
        }
        System.out.println("=========================");
        //获取指定公开的成员属性
        Field field1 = aClass.getField("name");
        System.out.println(field1);
        Field field2 = aClass.getField("price");
        System.out.println(field2);
        //获取指定的私有的成员属性
        Field field3 = aClass.getDeclaredField("id");
        System.out.println(field3);
        System.out.println("==========================");
        //对公开属性进行赋值
        Demo1 demo1 = (Demo1) aClass.getConstructor().newInstance();
        field1.set(demo1,"张三");
        field2.set(demo1,100.00);
        System.out.println(demo1);
        //对私有属性进行赋值
        //暴力反射
        field3.setAccessible(true);
        field3.set(demo1,10);
        System.out.println(demo1);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波波奶茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值