1股冗、線程安全
要搞清楚有狀態(tài)對象和無狀態(tài)對象,首先需要弄清楚線程安全的問題和蚪。如果你的代碼所在的進(jìn)程中有多個線程在同時運(yùn)行止状,而這些線程可能會同時運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的攒霹,而且其他的變量的值也和預(yù)期的是一樣的怯疤,那么就是線程安全的。
或者說催束,一個類或者程序所提供的接口對于線程來說是原子操作或者多個線程之間的切換不會導(dǎo)致該接口的執(zhí)行結(jié)果存在二義性集峦,也就是說我們不用考慮同步的問題。
線程安全問題都是由全局變量及靜態(tài)變量引起的抠刺。 若每個線程中對全局變量少梁、靜態(tài)變量只有讀操作,而無寫操作矫付,一般來說,這個全局變量是線程安全的第焰;若有多個線程同時執(zhí)行寫操作买优,一般都需要考慮線程同步,否則就可能影響線程安全挺举。
2杀赢、關(guān)于線程安全
1) 常量始終是線程安全的,因為只存在讀操作湘纵。
2) 每次調(diào)用方法前都新建一個實例是線程安全的脂崔,因為不會訪問共享的資源(共享堆內(nèi)存)。
3) 局部變量是線程安全的梧喷。因為每執(zhí)行一個方法砌左,都會在獨立的空間創(chuàng)建局部變量,它不是共享的資源铺敌。局部變量包括方法的參數(shù)變量和方法內(nèi)變量汇歹。
3、有狀態(tài)和無狀態(tài)對象
有狀態(tài)就是有數(shù)據(jù)存儲功能偿凭。有狀態(tài)對象(Stateful Bean)产弹,就是有實例變量的對象 ,可以保存數(shù)據(jù)弯囊,是非線程安全的痰哨。在不同方法調(diào)用間不保留任何狀態(tài)胶果。其實就是有數(shù)據(jù)成員的對象。
無狀態(tài)就是一次操作斤斧,不能保存數(shù)據(jù)早抠。無狀態(tài)對象(Stateless Bean),就是沒有實例變量的對象折欠。不能保存數(shù)據(jù)贝或,是不變類,是線程安全的锐秦。具體來說就是只有方法沒有數(shù)據(jù)成員的對象咪奖,或者有數(shù)據(jù)成員但是數(shù)據(jù)成員是可讀的對象。
4酱床、代碼示例
/**
* 有狀態(tài)bean,有state,user等屬性羊赵,并且user有存?zhèn)δ埽强勺兊摹? */
public class StatefulBean {
public int state;
// 由于多線程環(huán)境下扇谣,user是引用對象昧捷,是非線程安全的
public User user;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
/**
* 無狀態(tài)bean,不能存?zhèn)當(dāng)?shù)據(jù)。因為沒有任何屬性罐寨,所以是不可變的靡挥。只有一系統(tǒng)的方法操作。
*/
public class StatelessBeanService {
// 雖然有billDao屬性鸯绿,但billDao是沒有狀態(tài)信息的跋破,是Stateless Bean.
BillDao billDao;
public BillDao getBillDao() {
return billDao;
}
public void setBillDao(BillDao billDao) {
this.billDao = billDao;
}
public List<User> findUser(String Id) {
return null;
}
}