day02(多线程、反射、注解)

同步方法解决线程安全性问题

普通同步方法

import com.itheima.tikets.Student;

public class TicketsThread extends Thread {
    //100 张票 三个窗口售票
    //每一个窗口都有100张票 还是  三个窗口共同出售 100张票
    //被static修饰的属性的特点 只有一份  被所有的对象共享
    private static int tickets = 100;

    //锁对象的条件  被所有的线程共享  是一个惟一的
    private static Student stu = new Student();

    @Override
    public void run() {
        while(true){
            sell();
            if(tickets <= 0){
                break;
            }
        }
    }
    //普通同步方法 -- 无法解决
//    public synchronized void sell(){
        //锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
//        if (tickets > 0) {
//            System.out.println(getName() + "正在出售第" + tickets + "张票");
//            tickets--;
//        }
//    }
    //静态同步方法可以解决线程安全性问题?
    public static synchronized void sell(){
        //锁对象 -- 当前类的字节码对象 TicketsThread.class 唯一的 被所有的线程共享
        //锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
            tickets--;
        }
    }
}



public class Demo {
    public static void main(String[] args) {
        TicketsThread t1 = new TicketsThread();
        t1.setName("ww");
        TicketsThread t2 = new TicketsThread();
        t2.setName("yy");
        TicketsThread t3 = new TicketsThread();
        t3.setName("zz");
        t1.start();
        t2.start();
        t3.start();
    }
}

静态同步方法

public class TicketsThread implements Runnable {
    //100 张票 三个窗口售票
    //每一个窗口都有100张票 还是  三个窗口共同出售 100张票
    //被static修饰的属性的特点 只有一份  被所有的对象共享
    private static int tickets = 100;

    //锁对象的条件  被所有的线程共享  是一个惟一的
    private static Student stu = new Student();

    @Override
    public void run() {
        while(true){
            sell();
            if(tickets <= 0){
                break;
            }
        }
    }
    //普通同步方法 -- 无法解决
//    public synchronized void sell(){
//        //锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
//        if (tickets > 0) {
//            System.out.println(getName() + "正在出售第" + tickets + "张票");
//            tickets--;
//        }
//    }
    //静态同步方法可以解决线程安全性问题?
    public static synchronized void sell(){
        //锁对象 -- 当前类的字节码对象 TicketsThread.class 唯一的 被所有的线程共享
        //锁对象是谁? -- this 在继承这种方式里面不是唯一共享概的一个对象
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
            tickets--;
        }
    }
}
 public class TicketsDemo {
       public static void main(String[] args) {
           //因为runnable实现类对象只创建了一次  tickets 值被初始化一次 被三个线程所共享
           TicketsThread ticketsThread = new TicketsThread();
   
           //创建售票窗口 线程
           Thread t1 = new Thread(ticketsThread);
           Thread t2 = new Thread(ticketsThread);
           Thread t3 = new Thread(ticketsThread);
           t1.setName("ww");
           t2.setName(yy");
           t3.setName("zz");
           t1.start();
           t2.start();
           t3.start();
       }
   }

总结:

普通同步方法

解决实现Runnable这种方式  安全性问题

静态同步方法

解决继承 以及  实现 这两种方式的 安全性问题

properties

具备map的功能

增put删remove改put查get

特有的功能 -- 只能操作 String类型

public class PropertiesDemo_02 {
    public static void main(String[] args) {
        Properties properties = new Properties();
        properties.setProperty("itheima001","WW");
        properties.setProperty("itheima002","YY");
        properties.setProperty("itheima003","ZZ");
        for (String key : properties.stringPropertyNames()) {
            System.out.println(key + "---" + properties.getProperty(key));
        }
    }
}

反射

反射的前提是获取字节码对象

三种方式

1、对象.getClass();

2、类名.class

3、Class.forName(String className)

使用反射操作所有构造方法

public class RelectDemo_02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取字节码对象
        Class<?> clazz = Class.forName("com.itheima.reflect_02.Student");
        //2.获取私有的构造方法
//        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
//        for (Constructor<?> declaredConstructor : declaredConstructors) {
//            System.out.println(declaredConstructor);
//        }
        //Class<?>... parameterTypes 构造方法参数列表的数据类型
        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class);
        //3.使用私有的构造方法创建对象
        //Object ... initargs 参数的值
        //IllegalAccessException 当使用反射创建对象 或者 调用方法  属性  当前  这些构造 方法  属性 不可以调用的时候
        Object obj = declaredConstructor.newInstance("岳父大人");
        System.out.println(obj);
    }
}

使用反射操作所有的方法

  1. 获取字节码对象

  2. 创建对象

  3. 获取私有的方法

  4. 暴力访问

  5. 调用方法

public class MethodReflectDemo_02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1. 获取字节码对象
        Class<?> clazz = Class.forName("com.itheima.method.Student");
        //2. 创建对象
        Object obj = clazz.newInstance();
        //3. 获取私有的方法
        //String name,  方法名
        // Class<?>... parameterTypes 参数列表对应的类型
        Method showMethod = clazz.getDeclaredMethod("show", String.class);
        //4. 暴力访问
        showMethod.setAccessible(true);
        //5. 调用方法
        //Object obj,  调用的是哪一个对象的方法
        // Object... args 方法对应的参数
        showMethod.invoke(obj, "兰兰");
        //InvocationTargetException 当我们调用的方法 构造方法中出现异常的时候  抛出这个异常
    }
}

BeanUtils(populate方法)

public class BeanUtils {

    private BeanUtils(){}

    public static void setProperty(Object obj,String fieldName,Object value) throws Exception {
        //向student对象中赋值操作
        Class<?> clazz = obj.getClass();
        Field declaredField = clazz.getDeclaredField(fieldName);
        declaredField.setAccessible(true);
        declaredField.set(obj,value);
    }
    //使用方法进行赋值操作
    public static void setProperty2(Object obj,String fieldName,Object value) throws Exception{
        //获取字节码对象
        Class<?> clazz = obj.getClass();
        //获取方法进行赋值操作
        fieldName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1,fieldName.length());
        //获取所有的公共的方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            //method.getName() 获取方法名字
            if(fieldName.equals(method.getName())){
                method.invoke(obj,value);
            }
        }
    }

    public static Object getProperty(Object obj, String name) throws Exception {
        Class<?> clazz = obj.getClass();
        Field declaredField = clazz.getDeclaredField(name);
        //暴力访问
        declaredField.setAccessible(true);
        Object value = declaredField.get(obj);
        return value;
    }

    public static void populate(Object obj,Map<String,Object> map) throws Exception{
        Class<?> clazz = obj.getClass();

        for (String key : map.keySet()) {
            //将value写入到属性中
            //key -- 属性名  value -- 属性值
            //获取 属性对象
            //获取  key(属性名) 对应的字段
            Field keyField = clazz.getDeclaredField(key);
            //进行赋值操作
            keyField.setAccessible(true);
            keyField.set(obj,map.get(key));
        }
    }
}
public class Demo {
    public static void main(String[] args) throws Exception {
        Student student = new Student();
        //给哪一个属性赋值 赋什么值
        BeanUtils.setProperty2(student,"name","lisa");
        BeanUtils.setProperty2(student,"age",39);
        System.out.println(student);
        Object name = BeanUtils.getProperty(student, "name");
        System.out.println(name);

        System.out.println("--------------------------------");
        Map<String,Object> map = new HashMap<>();
        map.put("name","lisa");
        map.put("age",39);
        map.put("address","阜阳");
        map.put("id",111);

        //将集合中的内容 直接 写入到对象当中
        Student student1 = new Student();
        BeanUtils.populate(student1,map);
        System.out.println(student1);
    }
}

动态代理

Spring -- IOC AOP

IOC -- 控制反转

AOP -- 面向切面

OOP -- 面向对象

简单来讲 -- AOP 可以在不修改源码的情况下,增强某个功能

两种方案 :

其中一种 JDK提供的 动态代理 面像接口

Proxy

//1.创建一个接口  将需要准备增强的方法 抽取到接口中让 被代理对象  实现这个接口


public interface Star {
    public void sing(double money);

    public void jump(double money);

    public void rap(double money);

    public void basketball(double money);

    public void jiUSoBeautiful();
}
import java.sql.Statement;

public class CaiXuKun implements Star{
    public void sing(double money){
        System.out.println("给了" +money + "唱了一首歌曲" );
    }

    public void jump(double money){
        System.out.println("给了" +money + "跳起来了");
    }

    public void rap(double money){
        System.out.println("给了" +money + "唱了一首rap");
    }

    public void basketball(double money){
        System.out.println("给了" +money + "跳了一会篮球");
    }

    public void jiUSoBeautiful(){
        System.out.println("ye~~~~");
    }

    public void sleep(){
        System.out.println("欧ye,sleep 了");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Demo {
    public static void main(String[] args) {
        CaiXuKun cxk = new CaiXuKun();
        //1.创建一个接口  将需要准备增强的方法 抽取到接口中
        //让 被代理对象  实现这个接口
        //Proxy
        //ClassLoader loader,Class<?>[] interfaces,InvocationHandler h
        //loader 类加载器 -- 代理对象对应的类加载器
        ClassLoader classLoader = cxk.getClass().getClassLoader();
        //interfaces 代理对象 实现的所有的接口
        Class<?>[] interfaces = cxk.getClass().getInterfaces();
        //InvocationHandler 接口
        Star proxyObject = (Star) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            /*
            proxy 代理对象 proxyObject
            *method 方法 代理对象所调用的方法
            *args 参数 调用方法的时候  需要传递对应的参数
            * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //不要使用 proxy 调用方法
                //StackOverflowError
                //proxy.toString();
                String name = method.getName();
                Object invoke = null;
                if("sing".equals(name)){
                    invoke = method.invoke(cxk, args);
                }else{
                    System.out.println("签合同");
                    System.out.println("给钱");
                    invoke = method.invoke(cxk, args);
                    //返回值 动态代理调用的方法的返回值
                    System.out.println("合理避税");
                    System.out.println("打一顿....");
                }
                return invoke;
            }
        });

        proxyObject.sing(1000);
        proxyObject.basketball(2000);
        proxyObject.rap(2000);
        proxyObject.jiUSoBeautiful();
    }
}
发布了22 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_39115649/article/details/99225921