• 多线程不可变对象设计模式immutable


    immutable特点:

    1.不可变对象一定是线程安全的(里面的任何属性或者引用类型的属性一旦被初始化,都不能被修改)
    2.可变对象不一定是不安全的 StringBuffer

    题外话:

    J2EE中
    servlet 全局只创建一个对象,不是线程安全的
    struts 1.x Action也不是线程安全的,只创建一个Action实例
    struts 2.x Action是线程安全的,会为每一个请求创建一个Action实例

    一个不可变对象类

    package com.dwz.concurrency2.chapter8;
    
    public final class Person {
        private final String name;
        private final String address;
        
        public Person(String name, String address) {
            super();
            this.name = name;
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public String getAddress() {
            return address;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", address=" + address + "]";
        }
    }

    使用不可变对象的线程类

    package com.dwz.concurrency2.chapter8;
    
    public class UsePersonThread extends Thread {
        private Person person;
    
        public UsePersonThread(Person person) {
            this.person = person;
        }
        
        @Override
        public void run() {
            while (true) {
                System.out.println(Thread.currentThread().getName() + " print " + person.toString());
            }
        }
    }

    测试

    package com.dwz.concurrency2.chapter8;
    
    import java.util.stream.IntStream;
    
    public class ImmutableClient {
        public static void main(String[] args) {
            //share data
            Person person = new Person("Alex", "shanxi");
            IntStream.range(0, 5).forEach(i -> 
                new UsePersonThread(person).start()
            );
        }
    }

    不可变对象中对list引用的处理

    package com.dwz.concurrency2.chapter8;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public final class ImmutableTest {
        private final int age;
        private final String name;
        private final List<String> list;
        public ImmutableTest(int age, String name) {
            this.age = age;
            this.name = name;
            this.list = new ArrayList<>();
        }
        public int getAge() {
            return age;
        }
        public String getName() {
            return name;
        }
        public List<String> getList() {
            return Collections.unmodifiableList(list);
        }
    }

    举例说明在实现线程安全方面,不可变对象和synchronized的性能差异

    package com.dwz.concurrency2.chapter8;
    
    public class ImmutablePerformance {
        public static void main(String[] args) throws InterruptedException {
            long startTimeStamp = System.currentTimeMillis();
            //SyncObj 3742     单线程
            SyncObj syncobj = new SyncObj();
            syncobj.setName("Alex");
            for(long i = 0L; i < 1000000; i++) {
                System.out.println(syncobj.toString());
            }
            
            //ImmutableObj 3365 单线程
            ImmutableObj ImmutableObj = new ImmutableObj("dandan");
            for(long i = 0L; i < 1000000; i++) {
                System.out.println(ImmutableObj.toString());
            }
            
            //SyncObj 10009    多线程 16963
            //ImmutableObj 9452 多线程 16750
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    for(long i = 0L; i < 3000000; i++) {
                        System.out.println(Thread.currentThread().getName() + "=" + ImmutableObj.toString());
                    }
                }
            };
            
            Thread t2 = new Thread() {
                @Override
                public void run() {
                    for(long i = 0L; i < 1000000; i++) {
                        System.out.println(Thread.currentThread().getName() + "=" + ImmutableObj.toString());
                    }
                }
            };
            
            t1.start();
            t2.start();
            
            t1.join();
            t2.join();
            long endTimeStamp = System.currentTimeMillis();
            System.out.println("Elapsed time " + (endTimeStamp - startTimeStamp));
        }
    }
    
    final class ImmutableObj {
        private final String name;
        
        public ImmutableObj(String name) {
            this.name = name;
        }
        
        @Override
        public String toString() {
            return "[" + name + "]";
        }
    }
    
    class SyncObj {
        private String name;
        
        public synchronized void setName(String name) {
            this.name = name;
        }
        
        @Override
        public synchronized String toString() {
            return "[" + name + "]";
        }
    }

    结果表明:不可变对象确实比synchronized性能有所提升

    那么在实现自定义的Immutable的Class的时候,应该注意哪些要点呢?
    a)Class 应该定义成final,避免被继承。
    b)所有的成员变量应该被定义成final。
    c)不要提供可以改变类状态(成员变量)的方法。【get 方法不要把类里的成员变量让外部客服端引用,当需要访问成员变量时,返回成员变量的copy】
    d)构造函数不要引用外部可变对象。如果需要引用外部可以变量,应该在构造函数里进行defensive copy。

  • 相关阅读:
    【全程NOIP计划】分治与倍增
    apple id 后端验证 django
    安装Tomcat8,在Eclipse中配置Tomcat8
    CURL并发测试POST和DELETE请求
    curl如何发起DELETE/PUT请求?(备忘)
    Ubuntu 11.10下安装配置Zend Studio 9.0破解版详细步骤
    RTP QOS
    RTCP
    DirectDraw基础篇
    RTSP简介
  • 原文地址:https://www.cnblogs.com/zheaven/p/12123601.html
Copyright © 2020-2023  润新知