多线程之无状态对象和有状态对象

本文探讨了有状态对象和无状态对象的概念及其线程安全性。无状态对象因不存储数据而天然具备线程安全特性;有状态对象则需考虑成员变量是否被操作及变量的状态来确保线程安全。

从网上搜到的信息,有状态对象就是有数据存储功能的对象。无状态对象就是没有数据存储功能的对象。通俗地讲,有状态对象就是有成员变量的对象。


1、无状态对象一定是线程安全的

无状态对象因为不包含任何域,也不包含任何对其他类中域的引用,计算过程中的临时状态仅存在于线程栈的局部变量中,并且只能由正在执行的线程访问,当前线程不会影响到其他正在运行的线程,所以无状态对象一定是线程安全的。


2、有状态对象不一定是线程不安全的

(1)对象成员变量没有被操作:

public class StatefulBean {

	public int status;

	public int getStatus() {
		return status;
	}

	public void test(){
		System.out.println("此方法不操作成员变量status");
	}
}

上述代码中,虽然StatefulBean类有、成员变量status,但是因为该类中的方法没有操作该成员变量,所以即使该类的对象存在成员变量,也没有线程安全。

(2)成员变量是无状态对象的话,该对象也是线程安全的

public class StatefulTest {
	public static void main(String[] args) throws Exception {	
		Value value = new Value();	
		ThreadTest t1 = new ThreadTest(value, 1);
		ThreadTest t2 = new ThreadTest(value, 2);	
		t1.start();
		Thread.sleep(200);
		t2.start();	
	}
}

class ThreadTest extends Thread{
	private Value value;
	private int num;
	public ThreadTest(Value value, int num) {
		this.value = value;
		this.num = num;
	}
	@Override
	public void run() {
		value.test(num);
	}
}

class Value {
	public void test(int num) {
		int i = 0;
		if (num == 1) {
			i = 10;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else if (num == 2) {
			i = 20;
		}
		System.out.println("num = " + num + ", value = " + i);
	}
}

打印结果:

num = 2, value = 20
num = 1, value = 10

上述代码中,ThreadTest类中有成员变量Value,但是因为Value对象是无状态对象,所以ThreadTest是线程安全的。

当Value对象中有成员变量时:

class Value {
	int i = 0;
	public void test(int num) {
		if (num == 1) {
			i = 10;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else if (num == 2) {
			i = 20;
		}
		System.out.println("num = " + num + ", value = " + i);
	}
}

输出结果:

num = 2, value = 20
num = 1, value = 20

上述代码中,因为Value是有状态对象,且有操作该成员变量status的方法test(int num),所以该Value对象是线程不安全的。从而可以推出,ThreadTest也是线程不安全的。

结论:有状态的对象中,如果该对象的成员变量为无状态对象,或者该成员变量没有被操作,则该有状态对象也是线程安全的。都在是线程不安全的。















### Java中无状态对象有状态对象的区别及使用场景 #### 一、无状态对象的定义与特点 无状态对象是指其行为功能不依赖于内部状态的对象。这些对象在执行操作时不会保留任何数据,每次调用方法都基于输入参数进行处理[^1]。由于无状态对象没有内部变量或属性来存储状态信息,它们具有以下特点: - **线程安全**:由于无状态对象不维护任何内部状态,因此多个线程可以同时访问同一个实例而无需担心竞争条件。 - **可重用性**:无状态对象可以在不同上下文中重复使用,而不影响其行为。 - **易于测试**:因为行为仅依赖于输入参数,测试时无需考虑外部状态的变化。 示例代码如下: ```java public class StatelessCalculator { public int add(int a, int b) { return a + b; // 不依赖任何内部状态 } } ``` #### 二、有状态对象的定义与特点 有状态对象是指其行为功能依赖于内部状态的对象。这些对象通过实例变量保存数据,并在方法调用之间保持这些数据的持久性[^2]。有状态对象的特点包括: - **线程不安全**:如果多个线程同时访问一个有状态对象,可能会导致数据竞争或不一致的情况,除非采取同步措施。 - **复杂性较高**:由于需要管理内部状态,有状态对象的设计实现通常比无状态对象更复杂。 - **动态性**:有状态对象能够根据其内部状态的变化表现出不同的行为。 示例代码如下: ```java public class StatefulCounter { private int count; public void increment() { count++; // 修改内部状态 } public int getCount() { return count; } } ``` #### 三、无状态对象有状态对象的区别 | 特性 | 无状态对象 | 有状态对象 | |--------------------|-------------------------------------|-------------------------------------| | 内部状态 | 没有 | 有 | | 线程安全性 | 天然线程安全 | 需要额外的同步机制 | | 方法调用结果 | 仅依赖于输入参数 | 可能依赖于内部状态 | | 使用场景 | 工具类、函数式编程、不可变对象等 | 数据模型、业务逻辑、会话管理等 | #### 四、无状态对象的使用场景 无状态对象适用于那些不需要维护内部状态的场景,例如: - **工具类**:提供通用的静态方法,如`MathUtils`中的加法操作[^2]。 - **函数式编程**:Lambda表达式Stream API中的操作符通常表现为无状态特性,如过滤器`filter`[^1]。 - **不可变对象**:记录类(Record)是Java中的一种简化形式,用于表示不可变的数据载体[^2]。 示例代码: ```java record Point(int x, int y) {} // 记录类,天然无状态 Point p = new Point(10, 20); ``` #### 五、有状态对象的使用场景 有状态对象适用于需要维护内部状态的场景,例如: - **业务逻辑**:如学生成绩管理系统中的`Student`类,包含成绩数组并提供计算平均分的方法[^2]。 - **会话管理**:如Web应用中的用户会话对象,保存用户的登录状态其他相关信息。 - **缓存机制**:如内存缓存对象,保存频繁访问的数据以提高性能。 示例代码: ```java class Student { private String name; private double[] scores; public double getAverage() { double sum = 0; for (double score : scores) { sum += score; } return sum / scores.length; // 基于内部状态计算 } } ``` #### 六、总结 无状态对象有状态对象各有优劣,选择时应根据具体需求权衡。无状态对象适合简单、独立的操作,而有状态对象则适合需要维护复杂状态的场景。在多线程环境中,优先考虑无状态对象以减少同步开销[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值