电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

java this引用逃逸詳解

瀏覽:5日期:2022-08-20 11:03:57

1、什么是This逃逸?

在構(gòu)造器構(gòu)造還未徹底完成前(即實(shí)例初始化階段還未完成),將自身this引用向外拋出并被其他線程復(fù)制(訪問)了該引用,可能會(huì)問到該還未被初始化的變量,甚至可能會(huì)造成更大嚴(yán)重的問題。

廢話不多說,看一下代碼

/** * 模擬this逃逸 * @author Lijian * */ public class ThisEscape { //final常量會(huì)保證在構(gòu)造器內(nèi)完成初始化(但是僅限于未發(fā)生this逃逸的情況下,具體可以看多線程對final保證可見性的實(shí)現(xiàn)) final int i; //盡管實(shí)例變量有初始值,但是還實(shí)例化完成 int j = 0; static ThisEscape obj; public ThisEscape() { i=1; j=1; //將this逃逸拋出給線程B obj = this; } public static void main(String[] args) { //線程A:模擬構(gòu)造器中this逃逸,將未構(gòu)造完全對象引用拋出 /*Thread threadA = new Thread(new Runnable() { @Override public void run() { //obj = new ThisEscape(); } });*/ //線程B:讀取對象引用,訪問i/j變量 Thread threadB = new Thread(new Runnable() { @Override public void run() { //可能會(huì)發(fā)生初始化失敗的情況解釋:實(shí)例變量i的初始化被重排序到構(gòu)造器外,此時(shí)1還未被初始化 ThisEscape objB = obj; try { System.out.println(objB.j); } catch (NullPointerException e) { System.out.println('發(fā)生空指針錯(cuò)誤:普通變量j未被初始化'); } try { System.out.println(objB.i); } catch (NullPointerException e) { System.out.println('發(fā)生空指針錯(cuò)誤:final變量i未被初始化'); } } }); //threadA.start(); threadB.start(); } }

輸出結(jié)果:這說明ThisEscape還未完成實(shí)例化,構(gòu)造還未徹底結(jié)束。

發(fā)生空指針錯(cuò)誤:普通變量j未被初始化發(fā)生空指針錯(cuò)誤:final變量i未被初始化

另一種情況是利用線程A模擬this逃逸,但不一定會(huì)發(fā)生,線程A模擬構(gòu)造器正在構(gòu)造...而線程B嘗試訪問變量,這是因?yàn)?/p>

(1)由于JVM的指令重排序存在,實(shí)例變量i的初始化被安排到構(gòu)造器外(final可見性保證是final變量規(guī)定在構(gòu)造器中完成的);

(2)類似于this逃逸,線程A中構(gòu)造器構(gòu)造還未完全完成。

所以嘗試多次輸出(相信我一定會(huì)發(fā)生的,只是概率相對低),也會(huì)發(fā)生類似this引用逃逸的情況。

/** * 模擬this逃逸 * @author Lijian * */public class ThisEscape { //final常量會(huì)保證在構(gòu)造器內(nèi)完成初始化(但是僅限于未發(fā)送this逃逸的情況下) final int i; //盡管實(shí)例變量有初始值,但是還實(shí)例化完成 int j = 0; static ThisEscape obj; public ThisEscape() { i=1; j=1; //obj = this ; } public static void main(String[] args) { //線程A:模擬構(gòu)造器中this逃逸,將未構(gòu)造完全對象引用拋出 Thread threadA = new Thread(new Runnable() { @Override public void run() {//構(gòu)造初始化中...線程B可能獲取到還未被初始化完成的變量//類似于this逃逸,但并不定發(fā)生obj = new ThisEscape(); } }); //線程B:讀取對象引用,訪問i/j變量 Thread threadB = new Thread(new Runnable() { @Override public void run() {//可能會(huì)發(fā)生初始化失敗的情況解釋:實(shí)例變量i的初始化被重排序到構(gòu)造器外,此時(shí)1還未被初始化ThisEscape objB = obj;try { System.out.println(objB.j);} catch (NullPointerException e) { System.out.println('發(fā)生空指針錯(cuò)誤:普通變量j未被初始化');}try { System.out.println(objB.i);} catch (NullPointerException e) { System.out.println('發(fā)生空指針錯(cuò)誤:final變量i未被初始化');} } }); threadA.start(); threadB.start(); }}

2、什么情況下會(huì)This逃逸?

(1)在構(gòu)造器中很明顯地拋出this引用提供其他線程使用(如上述的明顯將this拋出)。

(2)在構(gòu)造器中內(nèi)部類使用外部類情況:內(nèi)部類訪問外部類是沒有任何條件的,也不要任何代價(jià),也就造成了當(dāng)外部類還未初始化完成的時(shí)候,內(nèi)部類就嘗試獲取為初始化完成的變量

在構(gòu)造器中啟動(dòng)線程:啟動(dòng)的線程任務(wù)是內(nèi)部類,在內(nèi)部類中xxx.this訪問了外部類實(shí)例,就會(huì)發(fā)生訪問到還未初始化完成的變量 在構(gòu)造器中注冊事件,這是因?yàn)樵跇?gòu)造器中監(jiān)聽事件是有回調(diào)函數(shù)(可能訪問了操作了實(shí)例變量),而事件監(jiān)聽一般都是異步的。在還未初始化完成之前就可能發(fā)生回調(diào)訪問了未初始化的變量。

在構(gòu)造器中啟動(dòng)線程代碼實(shí)現(xiàn):

/** * 模擬this逃逸2:構(gòu)造器中啟動(dòng)線程 * @author Lijian * */public class ThisEscape2 { final int i; int j; public ThisEscape2() { i = 1; j = 1; new Thread(new RunablTest()).start(); } //內(nèi)部類實(shí)現(xiàn)Runnable:引用外部類 private class RunablTest implements Runnable{ @Override public void run() { try {System.out.println(ThisEscape2.this.j); } catch (NullPointerException e) {System.out.println('發(fā)生空指針錯(cuò)誤:普通變量j未被初始化'); } try {System.out.println(ThisEscape2.this.i); } catch (NullPointerException e) {System.out.println('發(fā)生空指針錯(cuò)誤:final變量i未被初始化'); } } } public static void main(String[] args) { new ThisEscape2(); }}

構(gòu)造器中注冊事件,引用網(wǎng)上的一段偽代碼將以解釋:

public class ThisEscape3 { private final int var; public ThisEscape3(EventSource source) { //注冊事件,會(huì)一直監(jiān)聽,當(dāng)發(fā)生事件e時(shí),會(huì)執(zhí)行回調(diào)函數(shù)doSomething source.registerListener( //匿名內(nèi)部類實(shí)現(xiàn) new EventListener() {public void onEvent(Event e) {  //此時(shí)ThisEscape3可能還未初始化完成,var可能還未被賦值,自然就發(fā)生嚴(yán)重錯(cuò)誤 doSomething(e);} } ); var = 10; } // 在回調(diào)函數(shù)中訪問變量 int doSomething(Event e) { return var; }}

3、怎樣避免This逃逸?(1)單獨(dú)編寫一個(gè)啟動(dòng)線程的方法,不要在構(gòu)造器中啟動(dòng)線程,嘗試在外部啟動(dòng)。

...private Thread t;public ThisEscape2() { t = new Thread(new EscapeRunnable());}public void initStart() { t.start();}...

(2)將事件監(jiān)聽放置于構(gòu)造器外,比如new Object()的時(shí)候就啟動(dòng)事件監(jiān)聽,但是在構(gòu)造器內(nèi)不能使用事件監(jiān)聽,那可以在static{}中加事件監(jiān)聽,這樣就跟構(gòu)造器解耦了

static{ source.registerListener( new EventListener() {public void onEvent(Event e) { doSomething(e);} } ); var = 10; }}

4、總結(jié)

this引用逃逸問題實(shí)則是Java多線程編程中需要注意的問題,引起逃逸的原因無非就是在多線程的編程中“濫用”引用(往往涉及構(gòu)造器中顯式或隱式地濫用this引用),在使用到this引用的時(shí)候需要特別注意!

同時(shí)這會(huì)涉及到:final的內(nèi)存語義,即final域禁止重排序問題(2020.11.22增加),包括寫final域與讀final域重排序兩個(gè)規(guī)則(參考資料《Java并發(fā)編程的藝術(shù)》)

以上就是java this引用逃逸詳解的詳細(xì)內(nèi)容,更多關(guān)于java this引用逃逸的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 干洗加盟网-洗衣店品牌排行-干洗设备价格-干洗连锁加盟指南 | 北京模型公司-军事模型-工业模型制作-北京百艺模型沙盘公司 | 天然鹅卵石滤料厂家-锰砂滤料-石英砂滤料-巩义东枫净水 | 辐射仪|辐射检测仪|辐射巡测仪|个人剂量报警仪|表面污染检测仪|辐射报警仪|辐射防护网 | 家用净水器代理批发加盟_净水机招商代理_全屋净水器定制品牌_【劳伦斯官网】 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | pos机办理,智能/扫码/二维码/微信支付宝pos机-北京万汇通宝商贸有限公司 | 食药成分检测_调料配方还原_洗涤剂化学成分分析_饲料_百检信息科技有限公司 | 澳威全屋定制官网|极简衣柜十大品牌|衣柜加盟代理|全屋定制招商 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | 广州工业氧气-工业氩气-工业氮气-二氧化碳-广州市番禺区得力气体经营部 | 新疆乌鲁木齐网站建设-乌鲁木齐网站制作设计-新疆远璨网络 | 塑料熔指仪-塑料熔融指数仪-熔体流动速率试验机-广东宏拓仪器科技有限公司 | 美侍宠物-专注宠物狗及宠物猫训练|喂养|医疗|繁育|品种|价格 | 宝鸡市人民医院 | 深圳品牌设计公司-LOGO设计公司-VI设计公司-未壳创意 | 艾乐贝拉细胞研究中心 | 国家组织工程种子细胞库华南分库 | 嘉兴恒升声级计-湖南衡仪声级计-杭州爱华多功能声级计-上海邦沃仪器设备有限公司 | 吉祥新世纪铝塑板_生产铝塑板厂家_铝塑板生产厂家_临沂市兴达铝塑装饰材料有限公司 | 世界箱包品牌十大排名,女包小众轻奢品牌推荐200元左右,男包十大奢侈品牌排行榜双肩,学生拉杆箱什么品牌好质量好 - Gouwu3.com | 板框压滤机-隔膜压滤机-厢式压滤机生产厂家-禹州市君工机械设备有限公司 | 冷却塔厂家_冷却塔维修_冷却塔改造_凉水塔配件填料公司- 广东康明节能空调有限公司 | 干粉砂浆设备_干混砂浆生产线_腻子粉加工设备_石膏抹灰砂浆生产成套设备厂家_干粉混合设备_砂子烘干机--郑州铭将机械设备有限公司 | 同步带轮_同步带_同步轮_iHF合发齿轮厂家-深圳市合发齿轮机械有限公司 | 罗氏牛血清白蛋白,罗氏己糖激酶-上海嵘崴达实业有限公司 | 南京展台搭建-南京展会设计-南京展览设计公司-南京展厅展示设计-南京汇雅展览工程有限公司 | 酵素生产厂家_酵素OEM_酵素加盟_酵素ODM_酵素原料厂家_厦门益力康 | 免联考国际MBA_在职MBA报考条件/科目/排名-MBA信息网 | 防堵吹扫装置-防堵风压测量装置-电动操作显示器-兴洲仪器 | 铁盒_铁罐_马口铁盒_马口铁罐_铁盒生产厂家-广州博新制罐 | 广州办公室设计,办公室装修,写字楼设计,办公室装修公司_德科 | 卫生纸复卷机|抽纸机|卫生纸加工设备|做卫生纸机器|小型卫生纸加工需要什么设备|卫生纸机器设备多少钱一台|许昌恒源纸品机械有限公司 | 厌氧工作站-通用型厌氧工作站-上海胜秋科学仪器有限公司 | 办公室家具公司_办公家具品牌厂家_森拉堡办公家具【官网】 | 铝合金线槽_铝型材加工_空调挡水板厂家-江阴炜福金属制品有限公司 | 高温链条油|高温润滑脂|轴承润滑脂|机器人保养用油|干膜润滑剂-东莞卓越化学 | YAGEO国巨电容|贴片电阻|电容价格|三星代理商-深圳市巨优电子有限公司 | 电动高尔夫球车|电动观光车|电动巡逻车|电动越野车厂家-绿友机械集团股份有限公司 | 上海办公室装修,写字楼装修—启鸣装饰设计工程有限公司 | 最新电影-好看的电视剧大全-朝夕电影网 | 考试试题_试卷及答案_诗词单词成语 - 优易学 | 深圳办公室装修,办公楼/写字楼装修设计,一级资质 - ADD写艺 |