有状态对象与无状态对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012760435/article/details/88989825

最近在整理线程安全知识的时候发现了无状态对象这个名词,与之相关的叫有状态对象。百度搜索出来95%的内容都是一样的,而且代码残缺不全根本无从理解,想都不用想就知道是ctrl+c过来的。自己查阅各种资料大概理解了,现在整理一下备忘。


网上关于状态的解释还是很明白的。有状态对象(Stateful Bean)即有对应实例的对象,可以用来保存数据。EE开发中最常见的pojo就是有状态对象。无状态对象即不能保存(也可以叫不能修改)数据的,只能由当前线程进行访问,一次性操作,一锤子买卖。
POJO就是最常见的有状态对象,有成员变量(即数据字段),有变量的getter和setter方法,可以用来保存数据。
Spring工厂创建创建出来的Bean,包括controller,service,dao都是单例的,本身并不保存任何数据只是提供了一种操作,因此都是无状态对象。
无状态对象一定是线程安全的!有状态对象不一定是线程不安全的!无状态对象可以在一定操作下变为有状态对象,而且这种改变往往是不经意间造成的。
接下来分情况讨论一下。注意以下所有的类都不是特指的pojo类,UserInfo类完全可以是controller、service、dao等任意一个bean,不要思维定式看到get就认为是pojo,这是理解有状态对象的关键点。

成员变量没有被操作的有状态对象

标题根本看不懂,看代码。

public class UserInfo {
    private String name;

    public String getName() {
        return name;
    }
}

一个简单的类,有成员变量name,但是只有get方法没有set方法,所以成员变量的name值是无法被改变的,因此此对象线程安全。
同理,因为值没有被改变,下面的代码也是线程安全的。

public class UserInfo {
    private String name = "xiaoming";

    public String getName() {
        return name;
    }
}

总结:static 修饰的成员变量,或者等价于static修饰的成员变量都是线程安全的。虽然这是个有状态对象,但依然是线程安全。

成员变量是无状态对象的有状态对象

还是看不懂,看代码。

public class UserInfo {
    private String name = "xiaoming";
    private TestFunction testFunction = new TestFunction();
}

public class TestFunction {
	public void test() {
		int i = 0;
		System.out.println("It works!" + i);
	}
}

成员变量引用了另一个无状态对象,此时UserInfo仍然线程安全。

线程不安全的有状态对象

这里为了更具体一点用一个controller来进行说明。

@RestController
public class UserInfoController {
    @PostMapping("/create")
    public void createUser() {
    	// 调用业务层逻辑
    }
}

这是一个无状态的controller,现在是线程安全的。如果我稍加改动:

@RestController
public class UserInfoController {
    private int createCount = 0;
    
    @PostMapping("/create")
    public void createUser() {
    	count += 1;
    	// 调用业务层逻辑
    }
}

现在增加了成员变量createCount使得当前controller从原本的无状态对象转为了有状态对象;又因为createUser方法里面对createCount进行了自增操作,使得成员变量的值发生了改变,这种情况下就会出现线程安全问题。

总结

不要在controller、service、dao任何一层的实现类中创建成员变量并用来储存数据,否则web访问时一定会出现各种异常的错误。如确有必要,请使用ThreadLocal。

猜你喜欢

转载自blog.csdn.net/u012760435/article/details/88989825