从网上搜到的信息,有状态对象就是有数据存储功能的对象。无状态对象就是没有数据存储功能的对象。通俗地讲,有状态对象就是有成员变量的对象。
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也是线程不安全的。
结论:有状态的对象中,如果该对象的成员变量为无状态对象,或者该成员变量没有被操作,则该有状态对象也是线程安全的。都在是线程不安全的。