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) ;
                        }
                    }
                }
            }
        }

 

posted on 2018-04-26 16:55  飞机耳朵  阅读(189)  评论(0编辑  收藏  举报

导航