zoukankan      html  css  js  c++  java
  • 对JavaBean创建的一点改进

    在看了《Effective Java》Item2中对JavaBean的描述后,再结合Item1和Builder模式,遂想有没有其他方式避免JavaBean创建的线程安全问题呢?

    以如下JavaBean类为例,

    public class JavaBean {
    
        private int count;
        private String level;
        private List<String> messages;
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    
        public String getLevel() {
            return level;
        }
    
        public void setLevel(String level) {
            this.level = level;
        }
    
        public List<String> getMessages() {
            return messages;
        }
    
        public void setMessages(List<String> messages) {
            this.messages = messages;
        }
    }

    分步创建对象如下,因为几个set方法的调用导致对象的状态可能不一致,存在线程安全问题。比如javaBean对象在执行一系列set方法过程中,其他线程调用get方法,这时得到的属性值可能就不对了。

    JavaBean javaBean = new JavaBean();
    javaBean.setCount(1);
    javaBean.setLevel("first");
    javaBean.setMessages(new ArrayList<String>());

    为了避免创建过程中被访问,可以用匿名对象+链式调用的方式,如下代码,

    public class JavaBean {
    
        private int count;
        private String level;
        private List<String> messages;
    
        public int getCount() {
            return count;
        }
    
        public JavaBean setCount(int count) {
            this.count = count;
            return this;
        }
    
        public String getLevel() {
            return level;
        }
    
        public JavaBean setLevel(String level) {
            this.level = level;
            return this;
        }
    
        public List<String> getMessages() {
            return messages;
        }
    
        public JavaBean setMessages(List<String> messages) {
            this.messages = messages;
            return this;
        }
    }
    JavaBean javaBean1 = new JavaBean().setCount(1).setLevel("second").setMessages(new ArrayList<String>());
    System.out.println(javaBean1.getLevel());

    以上写法只有对象完全初始化好后,才将引用赋给javaBean1,避免创建过程中被其他线程访问。

    但这个时候,以上分步创建对象的方式仍然可以用。怎么能强制使用链式调用呢?想来想去觉得还得对链式调用进行封装。

    增加如下代码,

    private JavaBean(){ }
    
    public static JavaBean newInstance(){
        return new JavaBean();
    }
    
    public static JavaBean newInstance(int count, String level){
        return new JavaBean().setCount(count).setLevel(level);
    }

    这样一来,实际上跟直接使用参数化的构造函数一样,如下

    public JavaBean(){ }
    
    public JavaBean(int count, String level){
        this.count = count;
        this.level = level;
    }

    总结:

    1. 在写JavaBean时,set方法尽量返回JavaBean类型;

    2. 在创建对象时,尽量使用链式调用。

  • 相关阅读:
    (七)策略模式详解
    (六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)
    递归锁,死锁,使用递归锁解决死锁,信号量
    并发编程中的GIL锁(全局解释器锁)自己理解的他为啥存在
    线程了解以及创建线程的Threading模块中的部分方法
    进程 >> 互斥锁、队列与管道、生产者消费者模型
    进程比较基础的内容
    基于UDP协议的socket套接字编程 基于socketserver实现并发的socket编程
    网络基础 + 简易服务端和客户端
    单例模式
  • 原文地址:https://www.cnblogs.com/hello-yz/p/9844676.html
Copyright © 2011-2022 走看看