您好,登錄后才能下訂單哦!
這篇文章主要講解了“java如何發布與逸出對象”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“java如何發布與逸出對象”吧!
簡單來說就是提供一個對象的引用給作用域之外的代碼。比如return一個對象,或者作為參數傳遞到其他類的方法中。
不安全的發布對象示例:
@Slf4j
@NotThreadSafe
public class UnsafePublish {
private String[] states = {"a", "b", "c"};
public String[] getStates() {
return states;
}
public static void main(String[] args) {
UnsafePublish unsafePublish = new UnsafePublish();
log.info("{}", Arrays.toString(unsafePublish.getStates()));
// 發布對象不安全,可被修改
unsafePublish.getStates()[0] = "d";
log.info("{}", Arrays.toString(unsafePublish.getStates()));
}
}
如果一個類還沒有構造結束就已經提供給了外部代碼一個對象引用即發布了該對象,此時叫做對象逸出,對象的逸出會破壞線程的安全性。
public class Escape {
private int thisCanBeEscape = 1;
public Escape() {
new InnerClass();
// 還有業務需要執行
thisCanBeEscape++;
}
private class InnerClass {
public InnerClass() {
log.info("{}", Escape.this.thisCanBeEscape);
}
}
public static void main(String[] args) {
new Escape();
}
}
這個內部類的實例里面包含了對封裝實例的私有域對象的引用,在對象沒有被正確構造完成之前就會被發布,有可能有不安全的因素在里面,會導致this引用在構造期間溢出的錯誤。
上述代碼在函數構造過程中啟動了一個線程。無論是隱式的啟動還是顯式的啟動,都會造成這個this引用的溢出。新線程總會在所屬對象構造完畢之前就已經看到它了。
“類名.this”的語法在Java語言中叫做“qualified this”。 這個語法的主要用途是:在內部類的方法中,要指定某個嵌套層次的外圍類的“this”引用時,使用“外圍類名.this”語法。例如說:
class Foo { class Bar { Foo getFoo() { return Foo.this; } }}
在Foo.Bar類中的getFoo()方法中,如果直接寫“this”的話所指的是這個Foo.Bar類的實例,而如果要指定外圍的Foo類的this實例的話,這里就得寫成Foo.this。 特別的,如果在上例的getFoo()方法中寫Bar.this的話,作用就跟直接寫this一樣,指定的是當前的Foo.Bar類實例。
在靜態初始化函數中初始化一個對象引用
將對象的引用保存到volatile類型域或者AtomicReference對象中
將對象的引用保存到某個正確構造對象的final類型域中
將對象的引用保存到一個由鎖保護的域中
可以聯想下單例模式中餓漢模式/懶漢模式。
線程限制:一個被線程限制的對象,由線程獨占,并且只能被占有它的線程修改。
共享只讀:一個共享只讀的對象,在沒有額外同步的情況下,可以被多個線程并發訪問,但是任何線程都不能修改它。
線程安全對象:一個線程安全的對象或者容器,在內部通過同步機制來保證線程安全,所以其他線程無需額外的同步就可以通過公共接口隨意訪問它。
被守護對象:被守護對象只能通過獲取特定的鎖來訪問。
感謝各位的閱讀,以上就是“java如何發布與逸出對象”的內容了,經過本文的學習后,相信大家對java如何發布與逸出對象這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。