zoukankan      html  css  js  c++  java
  • java中反射-内省-代理模式-并发库下重入锁

    线程安全性
    ---------------
        1、同步
            同步代码块
            同步方法
        2、synchorize
            java中任何对象都可以作为锁旗标。
            对象内部维护了一个等待队列。
            多线程编程时涉及到生产消费关系,可以借助队列来完成。
            lock.wait()
            lock.wait(int n) ;
            lock.notify()
    
        
        3、sleep和wait区别
            sleep失去cpu抢占权,和锁定全无关。
            wait()失去cpu抢占权,失去锁定全。
    
    sync同步的缺点
    ----------------
        成本较高,
        Reente
        100张票    2个人售票员
        ------------------    
        sync        18,826,327ns
        lock        18,506,514ns    
    
    
    并发库下的ReentrantLock
    ------------------------
        1.ReentrantLock
            系统资源消耗较少。
            ReentrantLock lock = new ReentrantLock() ;
            //上锁
            lock.lock();
    
            //解锁
            lock.unlock();
    
        2.ReentrantReadWriteLock
            可重入读写锁,具有更加细的粒度。
            相当于乐观锁,支持一定程度的并发。
            读锁也叫共享读锁(共享性的)。
            写锁也就独占写锁(排他性的)。
            
            线程1                线程2.读锁    |    线程2.写锁
            -------------------------------------------------
            readLock()    |        ok            |    not ok
            -------------------------------------------------
            writeLock()    |        not ok        |    not ok
    
    
    ReentrantLock.lock()
    ------------------------
        1、解释
            如果其他线程没有持有该锁,请求锁定时会将计数器置为1。
            如果当前已经持有锁,计数器+1并即刻返回。
            如果被其他持有锁,当前线程不可用,处于休眠状态直到获得锁。
            并将计数器归1。
    
    ReentrantLock.tryLock()
    ------------------------
        1、解释
            尝试上锁,如果其他线程没上锁,上锁后立即返回,计数器归1,
            如果线程已上锁,立刻返回false。
    
    FairSync和NonfairSync
    ------------------------
        公平性同步和不公平同步机制。
        公平同步时排队机制,不公平机制是随机机制。
        默认是不公平机制,和notify()方法的机制是类似的。
        可重入锁内部通过同步对象实现的,而同步对象分为公平和不公平之分。
    
    
    Unsafe对象使用CAS机制实现原子性
    -----------------------
        1、简介
            compareAndSwap(),比较并交换.
    
            i ++
            i=1
            long i = 1 ;//32
    
    volatile
    ----------------------
        1、简介
            易变的,不稳定的,实时可见。
            使用该关键字修饰的成员变量被线程修改后,立即被其他线程所见。
            反之,其他线程有可能读到的仍然是修改之前的值。
    
    AtomicInteger原子整数的操作
    --------------------------
        1、简介
            该类内部封装了一个整数,通过底层unsafe类实现对该整数的操作符合原子性要求。
            提供了很多相应的方法:
            getAndIncrement()        //int y = i ++ , 先赋值后加减
            incrementAndGet()        //int y = ++ i , 
    
            getAndAdd(int x)        //int y = i ++ x
    
    并发库和sun底层库
    -------------------------
        ReentrantLock
        ReentrantReadWriteLock
        AtomicInteger
        sun.misc.Unsafe
    
    
    反射
    --------------------------
        1、Class
            类类,是类的描述符,描述java类的属性的。
    
        2、Method
            class.declaredMethods()        //声明的方法.
            class.methods()                //所有可见的方法。
    
        3、Field
            字段,成员变量。
            Field f = class.getDeclaredFiild("name") ;
    
        4、Constructor
            构造函数,构造器,构造子。
            //类的描述符
            Class clazz1 = Cat.class ;
            Constructor ctor1 = clazz1.getDeclaredConstructor(String.class) ;
            //
            ctor1.setAccessible(true);
            Object obj = ctor1.newInstance("tom");
            System.out.println(obj);
    
        5、反序列化对象,不经过构造。
            深度复制是通过java串行化技术实现。
            java类需要实现java.io.Serializable接口,改接口没有任何方法,是标识性接口。
            给jvm一个标记。使用transient修饰的成员变量不参与串行化过程,保持为null。
            transient可以减少内存消耗,避免不要对象的构建,节省内存。
            serialVersionUID串行ID主要用于反串过程,来完成类的版本比对的。
            Cat  cat = new Cat();
            cat.setName("tom");
            cat.setAge(12);
    
            FileOutputStream fos = new FileOutputStream("d:/cat.dat") ;
            ObjectOutputStream oos = new ObjectOutputStream(fos) ;
            oos.writeObject(cat);
            oos.close();
            fos.close();
    
        6、反串行是否经过构造函数
            反串行化时不经过构造函数。因为没必要,串行化对象的是状态(成员变量),
            串行化之后,状态是固定的,反串时只要恢复到对应状态即可,而构造函数是
            创建对象的过程,最终目的也是在成员变量上设定值。
    
        7.通过反射实现属性复制
            /**
             * 测试属性复制
             */
            @Test
            public void testPropertiesCopy() throws Exception {
                Cat a = new Cat() ;
                a.setName("tom");
                a.setAge(12);
                a.color = "red" ;
    
                Cat b = new Cat();
                copyProperties(a , b);
                System.out.println();
            }
    
            private static void copyProperties(Object a , Object b){
                try {
                    Class aClazz = a.getClass();
                    Class bClazz = b.getClass();
    
                    //得到a对象的所有字段
                    Field[] fs = aClazz.getDeclaredFields();
    
                    for(Field f : fs){
                        f.setAccessible(true);
                        Class ftype = f.getType();            //字段类型
                        String fname = f.getName() ;        //字段名称
                        Object value = f.get(a) ;            //字段值
    
                        try {
                            //得到b类中对应的字段
                            Field bf = bClazz.getDeclaredField(fname) ;
                            bf.setAccessible(true);
                            bf.set(b , value);
                        } catch (Exception e) {
                            continue;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
    
    内省
    -------------------
        1、简介
            专门用来操纵javabean的工具类,主要通过方法进行访问。
            [属性]
                getter/setter对应的名称部分。
                getName()
            [字段]
                成员变量
    
    
        2、实现属性复制
            @Test
            public void test1() throws Exception {
                Cat a = new Cat();
                a.setName("tom");
                a.setAge(12);
                a.setCategory("c1");
                Cat b = new Cat() ;
    
                copyProperties(a, b);
                System.out.println();
            }
    
            /**
             * 通过内省,操纵javabean,实现两个对象的属性复制。
             */
            public  static void copyProperties(Object a , Object b) throws Exception {
                //获得类的javabean信息
                BeanInfo abi = Introspector.getBeanInfo(a.getClass()) ;
                //得到所有属性描述符
                PropertyDescriptor[] apds = abi.getPropertyDescriptors();
    
                //获得类的javabean信息
                BeanInfo bbi = Introspector.getBeanInfo(b.getClass());
                //得到所有属性描述符
                PropertyDescriptor[] bpds = abi.getPropertyDescriptors();
    
                //迭代
                for(PropertyDescriptor pd : apds){
                    //得到属性名
                    String name = pd.getName() ;
                    Class apclazz=pd.getPropertyType() ;
                    //getter
                    Method getter = pd.getReadMethod();
    
                    if(getter != null){
                        getter.setAccessible(true);
                        for(PropertyDescriptor pd0 : bpds){
                            String bpname = pd0.getName();
                            Class bpclazz = pd0.getPropertyType();
                            Method bpsetter = pd0.getWriteMethod() ;
                            //ab两对象的属性名称和类型均相同
                            if(name.equals(bpname) && apclazz.equals(bpclazz) && bpsetter != null){
                                bpsetter.setAccessible(true);
                                Object value = getter.invoke(a) ;
                                bpsetter.invoke(b , value) ;
                            }
                        }
                    }
                }
            }
  • 相关阅读:
    团队冲刺第十天
    每日学习
    每日学习
    团队冲刺第九天
    每日学习
    2021.4.26
    2021.4.23
    2021.4.22
    2021.4.21
    2021.4.20
  • 原文地址:https://www.cnblogs.com/zyde/p/8953536.html
Copyright © 2011-2022 走看看