• Java Unsafe 测试代码


    Java Unsafe 测试代码

    import com.User;
    import org.junit.Before;
    import org.junit.Test;
    import sun.misc.Unsafe;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.UUID;
    import java.util.concurrent.CountDownLatch;
    
    class User {
    
        public static String USER_CLASS_NAME = "User.class";
        private int age;
        private String name;
    
        public int getAge() {
            return age;
        }
    
        public String getName() {
            return name;
        }
    
        public User(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    public class LockTests {
    
        Unsafe unSafe;
        User u = new User(17, "zhangsan");
    
        @Before
        public void before() throws Exception {
            Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeField.setAccessible(true);
            unSafe = (Unsafe) theUnsafeField.get(Unsafe.class);
        }
    
        @Test
        public void objectFieldOffset() throws Exception {
            // unSafe偏底层的一个Java工具类
            java.util.List users = new ArrayList();
            for (int i = 0; i < 10; i++) {
                Field ageField = User.class.getDeclaredField("age");
                User u = new User(18, "daxin");
                users.add(u);
                //使用内存获取User age字段在内存中的 offset
                // 是相对地址,不是一个绝对地址
                long ageOffset = unSafe.objectFieldOffset(ageField);
                // 每次都相同
                System.out.println("ageOffset = " + ageOffset);
            }
        }
    
        @Test
        public void compareAndSwapInt() throws Exception {
    
            // unSafe偏底层的一个Java工具类
            Field ageField = User.class.getDeclaredField("age");
    
            User u = new User(18, "daxin");
    
            //使用内存获取User age字段在内存中的 offset
            long ageOffset = unSafe.objectFieldOffset(ageField);
    
            // 修改之前的值
            System.out.println(u.getAge());
            // 进行CAS更新, 由于设置18 因此CAS 会成功
            unSafe.compareAndSwapInt(u, ageOffset, 18, 20);
            System.out.println(u.getAge());
    
            // 由于age设置20  进行CAS失败
            unSafe.compareAndSwapInt(u, ageOffset, 18, 22);
            System.out.println(u.getAge());
    
        }
    
        @Test
        public void ensureClassInitialized() {
            System.out.println("==== start ====");
            unSafe.ensureClassInitialized(ClassIsLoad.class);
            // 再次 确认不会报错
            unSafe.ensureClassInitialized(ClassIsLoad.class);
        }
    
        /**
         * AQS 底层的Node链表就是基于这个工具实现的 。
         *
         * @throws Exception
         */
        @Test
        public void getValueByFieldOffset() throws Exception {
            for (int i = 0; i < 10; i++) {
                User u = new User(18, UUID.randomUUID().toString().substring(i, 20));
                int age = unSafe.getInt(u, 12L);
                System.out.println("age = " + age);
    
                // 获取名字 field offset
                Field nameField = User.class.getDeclaredField("name");
                long nameOffset = unSafe.objectFieldOffset(nameField);
                System.out.println("nameOffset = " + nameOffset);
                String name = unSafe.getObject(u, nameOffset) + "";
                System.out.println("name = " + name);
            }
        }
    
        @Test
        public void pageSize() {
            System.out.println("unSafe.pageSize() = " + unSafe.pageSize());
        }
    
        /**
         * AtomicInteger 底层是基于getAndAddInt实现
         */
        @Test
        public void getAndAddInt() throws InterruptedException {
    
            User u = new User(17, "zhangsan");
            CountDownLatch downLatch = new CountDownLatch(10);
            System.out.println("u.getAge() = " + u.getAge());
            for (int i = 0; i < 10; i++) {
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        downLatch.countDown();
                        int val = unSafe.getAndAddInt(u, 12L, 1);
                        System.out.println(Thread.currentThread().getName() + "  val = " + val);
                    }
                }).start();
    
            }
            Thread.sleep(5000);
            System.out.println("u.getAge() = " + u.getAge());
        }
    
        @Test
        public void getAndSetInt() throws InterruptedException {
            User u = new User(17, "zhangsan");
            CountDownLatch downLatch = new CountDownLatch(10);
            System.out.println("u.getAge() = " + u.getAge());
            for (int i = 0; i < 10; i++) {
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        downLatch.countDown();
                        int val = unSafe.getAndSetInt(u, 12L, 10);
                        System.out.println(Thread.currentThread().getName() + "  val = " + val);
                    }
                }).start();
    
            }
            Thread.sleep(5000);
            System.out.println("u.getAge() = " + u.getAge());
        }
    
    
        @Test
        public void getIntVolatile() {
    
            for (int i = 0; i < 10; i++) {
                u.setAge(i);
                /**
                 * @param obj    the object containing the field to modify.
                 * @param offset the offset of the integer field within <code>obj</code>.
                 * @return
                 */
                int age = unSafe.getIntVolatile(u, 12L);
                System.out.println("age = " + age);
            }
        }
    
        // 系统负载采样的接口
        @Test
        public void getLoadAverage() {
            double[] nums = new double[8];
            int val = unSafe.getLoadAverage(nums, 8);
            System.out.println(val);
        }
    
    
        /**
         * //内存屏障,禁止load操作重排序。屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前
         * public native void loadFence();
         * <p>
         * <p>
         * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
         */
    
        @Test
        public void loadFence() {
            //java.util.concurrent.locks.StampedLock.validate
            unSafe.loadFence();
        }
    
        /**
         * //内存屏障,禁止store操作重排序。屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前
         * public native void storeFence();
         * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
         */
        @Test
        public void storeFence() {
        }
    
        /**
         * //内存屏障,禁止load、store操作重排序
         * public native void fullFence();
         * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
         */
        @Test
        public void fullFence() {
        }
    
    
        @Test
        public void shouldBeInitialized() {
            boolean shouldBeInitialized = unSafe.shouldBeInitialized(String.class);
            System.out.println(shouldBeInitialized);
            shouldBeInitialized = unSafe.shouldBeInitialized(User.class);
            System.out.println(shouldBeInitialized);
        }
    
        /**
         * synchronized 的一种实现获取锁
         *
         * @throws InterruptedException
         */
        @Test
        public void monitorEnter() throws InterruptedException {
    
            unSafe.monitorEnter(u);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (u) {
                        System.out.println("==u lock got ==");
                    }
                }
            }).start();
    
            Thread.sleep(2000);
            unSafe.monitorExit(u);
        }
    
        @Test
        public void compareAndSwap() {
    //        unSafe.compareAndSwapInt(对象, 对象中的字段偏移, 期望值, 设置值)
    //        unSafe.compareAndSwapLong(对象, 对象中的字段偏移, 期望值, 设置值)
    //        unSafe.compareAndSwapObject(对象, 对象中的字段偏移, 期望值, 设置值)
        }
    
        @Test
        public void t() {
            // 方法签名
            // public void copyMemory(Object srcBase, long srcOffset,Object destBase, long destOffset, long bytes)
            // unSafe.copyMemory();
        }
    
    
    }
    
    
    class ClassIsLoad {
    
        static {
            System.out.println("ClassIsLoad class Is Load !");
        }
    }
    

      

  • 相关阅读:
    AvalonDock使用体验
    使用vs2015时,拖拉窗口,窗口隐藏后点击显示就会报错,错误代码“已在“VisualTreeChanged”事件期间更改可视化树”。
    es6的常用新特性
    js如何准确获取当前页面url网址信息
    移动端1px细线解决方案总结
    Zepto tap 穿透bug、解决移动端点击穿透问题
    js继承的方式有几种
    js常用的几种模式
    判断对象类型 typeof instanceof Object.prototype.tostring()
    new的实现机制
  • 原文地址:https://www.cnblogs.com/leodaxin/p/13556615.html
Copyright © 2020-2023  润新知