Tesla獲香港數百台電動汽車訂單

據彭博上周報導,電動跑車製造商特斯拉汽車(Tesla Motors Inc.)生產的Model S已在香港接獲數百台訂單。Model S預定要在今(2013)年冬季於香港開賣,定價會在數個月內公佈。Model S在美國定價為69,900美元,Tesla預估這款車種今年有望賣出21,000台。

福特汽車(Ford Motor Co.)擴大推出油電混合車、電動車,加上Tesla的豪華電動車需求熱絡,帶動美國上半年電動轎車、卡車銷售上揚。根據彭博統計,美國今年上半年油電混合車、電動車銷售量上升至少23%至超過287,000台。

Tesla直接對消費者販售跑車的模式在美國面臨諸多阻撓,由於美國法律規定車輛必須由擁有經銷商執照的業者販售,因此特斯拉在美國多處皆無法開賣。不過,由Tesla車迷自行在白宮網站發起的請願活動已達到向總統歐巴馬(Barack Obama)要求回應的門檻,這有望為特斯拉解套。

Tesla才剛繳出了亮眼的財報成績單,同時還提前償還了政府貸款。Tesla執行長Elon Musk曾表示,他要大規模擴展Tesla快速充電站的美國網絡,預期到了6月底為止,充電站的涵蓋區域有望擴增3倍。他還說,到了今年底,Tesla車主將可靠著快速充電站,從洛杉磯直接開車到紐約。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

Tesla電動車北美Q2售出5千多台,營收超4億美元

美國電動車商Tesla近日公布最新財報,Q2營收達到4.051億美元,北美市場銷售5千多台,遠高於目標4千台,EPS 0.2美元毛利率由前一季的17%拉升到了22%。

Tesla電動車的充電器看上去像加油槍,充飽電后可跑25公里,而後車廂配備大顆鋰電池,用家用插座可充飽電4.5度電,最高時速一小時85公里,花費比油車節省很多。

被喻為車界「蘋果」的Tesla ModelS,一台要價7萬美金,底部有整顆電池可跑200公里,車內配製17吋觸控電腦,第二季在北美市場賣出5150輛,大幅超過4500輛的目標,成為車市的大黑馬。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

Domain Adaptive Faster R-CNN:經典域自適應目標檢測算法,解決現實中痛點,代碼開源 | CVPR2018

論文從理論的角度出發,對目標檢測的域自適應問題進行了深入的研究,基於H-divergence的對抗訓練提出了DA Faster R-CNN,從圖片級和實例級兩種角度進行域對齊,並且加入一致性正則化來學習域不變的RPN。從實驗來看,論文的方法十分有效,這是一個很符合實際需求的研究,能解決現實中場景多樣,訓練數據標註有限的情況。

來源:曉飛的算法工程筆記 公眾號

論文: Domain Adaptive Faster R-CNN for Object Detection in the Wild

  • 論文地址:https://arxiv.org/pdf/1803.03243.pdf
  • 論文代碼:https://github.com/yuhuayc/da-faster-rcnn

Introduction

  目前,目標檢測算法在公開數據上有很好的表現,但在現實世界環境中通常會有許多特殊的挑戰,比如視角、物體外觀、背景、光照以及圖片質量的不同,使得測試數據和訓練數據存在較大的跨偏移問題。

  以自動駕駛為例,不同的公開數據集里的圖片存在較大的差異,域偏移問題會導致明顯的檢測器性能下降。儘管收集更多的訓練圖片能解決域偏移的影響,但顯然這不是最好的方案。
  為了解決上面的問題,論文提出Domain Adaptive Faster R-CNN,最小化圖片級別域偏移(圖片尺寸、圖片風格、光照等)以及實例級域偏移(目標外表、目標尺寸等),每個模塊學習一個域分類器並且通過對抗訓練學習域不變的特徵,並且加入分類器的一致性正則化來保證RPN學習到域不變的proposal。
  論文的主要貢獻如下:

  • 從概率角度對跨域目標檢測中的域偏移問題進行理論分析。
  • 設計了兩個域自適應模塊來消除圖片級別和實例級別的域差異。
  • 提出一致性正則化來學習域不變RPN。
  • 將提出的模塊集成到Faster R-CNN中,進行端到端的訓練。

Distribution Alignment with H-divergence

  論文設計了H-divergence度量兩個不同分佈的樣本集,定義$x$為特徵向量,$x_{\mathcal{S}}$為源域樣本$x_{\mathcal{T}}$為目標域樣本,$h:x\to {0,1}$為域分類器,預測源域樣本$x_{\mathcal{S}}$為0,預測目標域樣本$x_{\mathcal{T}}$為1。假設$\mathcal{H}$為一組域分類器,則H-divergence的定義為:

  $err_{\mathcal{S}}$和$err_{\mathcal{T}}$為$h(x)$在源域和目標域樣本的預測誤差,上述的公式意味着域距離$d_{\mathcal{H}}(\mathcal{S},\mathcal{T})$與域分類器的錯誤率成反比,若最好的域分類器的錯誤率越高,則源域和目標域的距離越近。
  在神經網絡中,定義網絡$f$產生特徵向量$x$,為了進行域對齊,需要網絡$f$產生能夠減小域距離$d_{\mathcal{H}}(\mathcal{S},\mathcal{T})$的特徵向量,即最小化公式:

  上述的公式可以通過對抗訓練進行優化,論文採用gradient reverse
layer(GRL)進行實現,訓練主幹特徵最大化域分類誤差並且訓練域分類器最小域分類誤差進行對抗訓練,最終得出魯棒的特徵。

Domain Adaptation for Object Detection

A Probabilistic Perspective

  目標檢測問題可表示為後驗概率$P(C, B|I)$,$I$為圖片,$B$為目標的bbox,$C\in {1,\cdots,K}$為目標類別。定義目標檢測的樣本的聯合分佈為$P(C,B,I)$,其中源域和目標域的分佈是不一樣的$P_{\mathcal{S}}(C,B,I) \neq P_{\mathcal{T}}(C,B,I)$

  • Image-Level Adaptation

  根據貝恭弘=叶 恭弘斯公式,目標檢測的聯合分佈可定義為

  定義目標檢測為covariate shift假設,設定域間的條件概率$P(C, B|I)$是一樣的,域分佈偏移主要來自於$P(I)$分佈的不同。在Faster R-CNN中,$P(I)$即從圖片提取的特徵,所以要解決域偏移問題,就要控制$P_{\mathcal{S}}(I)=P_{\mathcal{T}}(I)$,保證不同域的圖片提取的特徵一致。

  • Instance-Level Adaptation

  另一方面,目標檢測的聯合分佈也可以定義為

  基於covariate shift假設,設定域間的條件概率$P(C|B,I)$是一樣的,域分佈偏移主要來自於$P(B,I)$分佈的不同,而$P(B,I)$即圖像中bbox區域特徵,所以為了解決域偏移問題,需要控制$P_{\mathcal{S}}(B,I)=P_{\mathcal{T}}(B,I)$,保證不同域的圖片提取的相同目標的bbox特徵不變。
  需要注意的是,目標域是沒有標註信息的,只能通過$P(B,I)=P(B|I)P(I)$獲取,$P(B|I)$為bbox預測器,這樣就需要RPN具備域不變性,為此,論文再添加了Joint Adaptation。

  • Joint Adaptation

  考慮到$P(B,I)=P(B|I)P(I)$,而分佈$P(B|I)$是域不變且非零的,因此有

  若域間的圖片級特徵的分佈是一樣的,實例級特徵的分佈也應該是一樣的。但實際中很難達到完美的$P(B|I)$,首先$P(I)$分佈很難完美地對齊,導致$P(B|I)$的輸入有偏,其次bbox是從源域學習而來的,會存在一定地偏差。
  為此,論文使用一致性正則化來消除$P(B|I)$的偏置,使用域分類器$h(x)$來進行源域和目標域的判斷。定義域標籤為$D$,圖像級分類器可看為預測$P(D|I)$,實例級的分類器可看為預測$P(D|B,I)$。根據貝恭弘=叶 恭弘斯理論,得到

  其中,$P(B|I)$是域不變的bbox預測器,而$P(B|D,I)$為域相關的bbox預測器。由於目標域沒有標註的bbox,所以實際僅學習到域相關的bbox預測器$P(B|D,I)$。但可以通過強制兩種分類器的一致性$P(D|B,I)=P(D|I)$,使得$P(B|D,I)$逼近$P(B|I)$。

Domain Adaptation Components

  DA Faster R-CNN的架構如圖2所示,包含兩個域自適應模塊以及一致性正則化模塊,自適應模塊加入GRL(gradient reverse layer)進行對抗訓練,每個模塊包含一個域分類器,最終的損失函數為

  • Image-Level Adaptation

  為了消除圖片級域分佈不匹配,使用patch-based域分類器對特徵圖的每個特徵點進行分類,每個特徵點實際對應原圖的一片區域$I_i$,這樣特徵點域分類器就等同於預測了每個圖像中每個patch的域標籤,這樣的好處在於:

  • 圖片級表達的對齊通常能有助於消除整圖帶來的偏移。
  • 由於目標檢測算法的batch size通常很小,path-based能夠提高域分類器的訓練樣本數。

  定義$D_i$為第$i$個訓練圖片的域標籤,$\phi_{u,v}(I_i)$為特徵圖上的一個激活值,$p^{(u,v)}_i$為域分類器的一個輸出,則圖片級自適應損失為

  為了對齊域分佈,需要同時優化域分類器最小化域分類損失以及優化主幹網絡的參數最大化域分類損失進行對抗訓練,論文採用GRL進行實現,使用梯度下降來訓練域分類器,回傳梯度給主幹時將梯度置為反符號。

  • Instance-Level Adaptation

  實例級特徵對齊有助於減少實例的局部差異,比如外表,大小,視角等。跟圖片級特徵對齊類似,定義$p_{i,j}$為第$i$個圖片的第$j$個proposal,實例級的自適應損失為

  同樣的,在域分類器前添加GRL模塊進行對抗訓練。

  • Consistency Regularization

  如前面的分析,強制域分類器的一致性有助於學習魯棒的跨域bbox預測器,加入一致性正則化。由於圖片級域分類器是對特徵值進行分類的,取平均輸出作為圖片級概率,一致性正則化為

  其中$|I|$為特徵圖的點數,$||\cdot||$為$\mathcal{l}_2$距離。

Experiments

Learning from Synthetic Data

  SIM 10k是從GTAV中截取畫面進行標註的數據集,Cityscapes為真實圖片,這裏對比從生成圖片到真實圖片的域轉移。

Driving in Adverse Weather

  Foggy Cityscapes通過生成霧來模擬真實場景,這裏對比天氣帶來的域轉移。

Cross Camera Adaptation

  這裏對比兩個不同的訓練數據集的域對齊。

Error Analysis on Top Ranked Detections

  每個模塊都能提升一定的準確率,而圖片級對齊的背景錯誤率較高,這可能由於圖片級對齊對RPN的提升更直接。

Image-level v.s. Instance-level Alignment

Consistency Regularization

CONCLUSION

  論文從理論的角度出發,對目標檢測的域自適應問題進行了深入的研究,基於H-divergence的對抗訓練提出了DA Faster R-CNN,從圖片級和實例級兩種角度進行域對齊,並且加入一致性正則化來學習域不變的RPN。從實驗來看,論文的方法十分有效,這是一個很符合實際需求的研究,能解決現實中場景多樣,訓練數據標註有限的情況。



如果本文對你有幫助,麻煩點個贊或在看唄~
更多內容請關注 微信公眾號【曉飛的算法工程筆記】

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

美國八大州擬擴建充電站等 提升電動汽車普及率

為增加電動汽車普及率,美國加州、紐約及其它6州政府昨(24) 日聯合發布聲明,將廣設充電站、修改營建法條,務求使一般市民也能輕鬆擁有、享受電動汽車。

加州、紐約、麻州、康乃狄克、馬里蘭、羅德島、佛蒙特、奧勒崗等州,合計銷售佔比已超過美國汽車市場的25%。其中,加州是美國最大的汽車銷售市場。

據紐約時報報導,到2025年,州政府希望零碳排放汽車(包含電動汽車與燃料電池汽車)銷量至少能達到330萬輛的目標。

美國電動汽車製造商特斯拉(Tesla)昨天宣布,成功挖腳蘋果產品設計副總裁Doug Field,他在蘋果公司任職時,曾是MacBook Air、MacBook Pro、與iMac等明星級產品的幕後推手。Field之前還在福特汽車任職過,未來他將領導特斯拉汽車研發部門。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

全國環保盃桌球錦標賽基隆登場 41支隊伍以球會友

第一次在基隆市舉辦的「全國第32屆環保盃桌球錦標賽」,自9日起一連三天在體育館熱鬧開打,市長林右昌也以地主台北網頁設計身份歡迎全國各縣市環保單位41支隊伍、近500名桌球好手來到基隆,並期許選手們除了以球會友,也別忘了好好欣新北清潔賞基隆的山海美景。

開幕典禮由基隆市長林右昌及環保署署長張子敬到場勉勵選手,並在台上進行開iphone維修球儀式。林右昌代表基隆市民歡迎全國各縣市選手的到來,希望在大FB行銷會的妥善安排下,能讓選手賓至如歸,展現最佳實力,並提醒選台北網頁設計手們除了透過比賽相互交流切磋球技,也別忘了盡情享受基隆的在地文化。

林右昌表示,這屆的環保盃桌球錦標賽是32年貨運來首度在基隆舉行,過去由於基隆市的運動場館場地環境條件不太好,因此無租車法舉辦全國賽事,這幾年來市府把包括市立體育館的運動空間及游泳池大幅整修,讓大家享受優質的運動環境,除了比賽之外銷售文案也歡迎大家在基隆住宿,並且進行觀光遊程,𣈱遊基隆的好山好水。

環保局指出,市府如何寫文案將安排選手前往有「網頁設計台灣龍珠」美譽的基隆嶼,以及海科館、和平島等地,進行環保網頁設計公司業務交流活動,讓各地的環保夥伴能夠對基隆有更進一步的瞭解。

環保盃桌球錦標賽是從環保署成立之初就開始舉辦,每年由包裝行銷各縣市環保局輪流辦理,今年已邁入第32年,除網頁設計讓各縣市環保人員有聯誼交流機會,也鼓勵大家運動強身,發揮團隊精神,讓工作更有效率。

光靠撤資還不夠 外媒:擺脫化石燃料 國際合作有必要

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

比亞迪與戴姆勒合作電動汽車2014年有望面市

比亞迪高級副總裁廉玉波近日表示,比亞迪與奔馳合作的一款高端電動汽車目前已完成研發進入測試階段,預計2014年4月的北京車展就能面市。

據公開資料顯示,2010年5月27日,比亞迪與奔馳母公司戴姆勒簽署合同,在中國成立深圳比亞迪-戴姆勒新技術有限公司,雙方各佔50%股權,注冊資本為6億元人民幣。

與傳統的“市場換技術”中外合資企業模式不同,本著品牌平等和技術平等的合作方式,比亞迪與戴姆勒共同擁有一個新品牌。雙方從零部件、整車性能、整車標准各方面進行研發合作,德國戴姆勒方面隻提供方案,而比亞迪的研發團隊將親自參與具體實踐。

2011年10月31日,新京報曾報道,比亞迪與奔馳合作的電動車樣車設計已接近尾聲,預計售價為50萬元左右,2012年4月將於北京車展面市。但這款高端電動汽車卻遲遲不見上市。

除了這款高端電動汽車之外,比亞迪方面還有兩款新能源車型也處於研發之中。其中 “唐”是一款搭載2.0TID和大電機的混合動力SUV車型,該車的百公裡加速時間將縮短至3.9秒,預計將於2014年上市。另一款e6的升級版車型也在研發之中。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

Spring如何解決循環依賴?

介紹

先說一下什麼是循環依賴,Spring在初始化A的時候需要注入B,而初始化B的時候需要注入A,在Spring啟動后這2個Bean都要被初始化完成

Spring的循環依賴有兩種場景

  1. 構造器的循環依賴
  2. 屬性的循環依賴

構造器的循環依賴,可以在構造函數中使用@Lazy註解延遲加載。在注入依賴時,先注入代理對象,當首次使用時再創建對象完成注入

屬性的循環依賴主要是通過3個map來解決的

構造器的循環依賴

@Component
public class ConstructorA {

	private ConstructorB constructorB;

	@Autowired
	public ConstructorA(ConstructorB constructorB) {
		this.constructorB = constructorB;
	}
}
@Component
public class ConstructorB {

	private ConstructorA constructorA;

	@Autowired
	public ConstructorB(ConstructorA constructorA) {
		this.constructorA = constructorA;
	}
}
@Configuration
@ComponentScan("com.javashitang.dependency.constructor")
public class ConstructorConfig {
}
public class ConstructorMain {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(ConstructorConfig.class);
		System.out.println(context.getBean(ConstructorA.class));
		System.out.println(context.getBean(ConstructorB.class));
	}
}

運行ConstructorMain的main方法的時候會在第一行就報異常,說明Spring沒辦法初始化所有的Bean,即上面這種形式的循環依賴Spring無法解決。

我們可以在ConstructorA或者ConstructorB構造函數的參數上加上@Lazy註解就可以解決

@Autowired
public ConstructorB(@Lazy ConstructorA constructorA) {
	this.constructorA = constructorA;
}

因為我們主要關注屬性的循環依賴,構造器的循環依賴就不做過多分析了

屬性的循環依賴

先演示一下什麼是屬性的循環依賴

@Component
public class FieldA {

	@Autowired
	private FieldB fieldB;
}
@Component
public class FieldB {

	@Autowired
	private FieldA fieldA;
}
@Configuration
@ComponentScan("com.javashitang.dependency.field")
public class FieldConfig {
}
public class FieldMain {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(FieldConfig.class);
		// com.javashitang.dependency.field.FieldA@3aa9e816
		System.out.println(context.getBean(FieldA.class));
		// com.javashitang.dependency.field.FieldB@17d99928
		System.out.println(context.getBean(FieldB.class));
	}
}

Spring容器正常啟動,能獲取到FieldA和FieldB這2個Bean

屬性的循環依賴在面試中還是經常被問到的。總體來說也不複雜,但是涉及到Spring Bean的初始化過程,所以感覺比較複雜,我寫個demo演示一下整個過程

Spring的Bean的初始化過程其實比較複雜,為了方便理解Demo,我就把Spring Bean的初始化過程分為2部分

  1. bean的實例化過程,即調用構造函數將對象創建出來
  2. bean的初始化過程,即填充bean的各種屬性

bean初始化過程完畢,則bean就能被正常創建出來了

下面開始寫Demo,ObjectFactory接口用來生產Bean,和Spring中定義的接口一樣

public interface ObjectFactory<T> {
	T getObject();
}
public class DependencyDemo {

	// 初始化完畢的Bean
	private final Map<String, Object> singletonObjects =
			new ConcurrentHashMap<>(256);

	// 正在初始化的Bean對應的工廠,此時對象已經被實例化
	private final Map<String, ObjectFactory<?>> singletonFactories =
			new HashMap<>(16);

	// 存放正在初始化的Bean,對象還沒有被實例化之前就放進來了
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	public  <T> T getBean(Class<T> beanClass) throws Exception {
		// 類名為Bean的名字
		String beanName = beanClass.getSimpleName();
		// 已經初始化好了,或者正在初始化
		Object initObj = getSingleton(beanName, true);
		if (initObj != null) {
			return (T) initObj;
		}
		// bean正在被初始化
		singletonsCurrentlyInCreation.add(beanName);
		// 實例化bean
		Object object = beanClass.getDeclaredConstructor().newInstance();
		singletonFactories.put(beanName, () -> {
			return object;
		});
		// 開始初始化bean,即填充屬性
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			// 獲取需要注入字段的class
			Class<?> fieldClass = field.getType();
			field.set(object, getBean(fieldClass));
		}
		// 初始化完畢
		singletonObjects.put(beanName, object);
		singletonsCurrentlyInCreation.remove(beanName);
		return (T) object;
	}

	/**
	 * allowEarlyReference參數的含義是Spring是否允許循環依賴,默認為true
	 * 所以當allowEarlyReference設置為false的時候,當項目存在循環依賴,會啟動失敗
	 */
	public Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null 
				&& isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory =
							this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
					}
				}
			}
		}
		return singletonObject;
	}

	/**
	 * 判斷bean是否正在被初始化
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

}

測試一波

public static void main(String[] args) throws Exception {
	DependencyDemo dependencyDemo = new DependencyDemo();
	// 假裝掃描出來的對象
	Class[] classes = {A.class, B.class};
	// 假裝項目初始化所有bean
	for (Class aClass : classes) {
		dependencyDemo.getBean(aClass);
	}
	// true
	System.out.println(
			dependencyDemo.getBean(B.class).getA() == dependencyDemo.getBean(A.class));
	// true
	System.out.println(
			dependencyDemo.getBean(A.class).getB() == dependencyDemo.getBean(B.class));
}

是不是很簡單?我們只用了2個map就搞定了Spring的循環依賴

2個Map就能搞定循環依賴,那為什麼Spring要用3個Map呢?

原因其實也很簡單,當我們從singletonFactories中根據BeanName獲取相應的ObjectFactory,然後調用getObject()這個方法返回對應的Bean。在我們的例子中
ObjectFactory的實現很簡單哈,就是將實例化好的對象直接返回,但是在Spring中就沒有這麼簡單了,執行過程比較複雜,為了避免每次拿到ObjectFactory然後調用getObject(),我們直接把ObjectFactory創建的對象緩存起來不就行了,這樣就能提高效率了

比如A依賴B和C,B和C又依賴A,如果不做緩存那麼初始化B和C都會調用A對應的ObjectFactory的getObject()方法。如果做緩存只需要B或者C調用一次即可。

知道了思路,我們把上面的代碼改一波,加個緩存。

public class DependencyDemo {

	// 初始化完畢的Bean
	private final Map<String, Object> singletonObjects =
			new ConcurrentHashMap<>(256);

	// 正在初始化的Bean對應的工廠,此時對象已經被實例化
	private final Map<String, ObjectFactory<?>> singletonFactories =
			new HashMap<>(16);

	// 緩存Bean對應的工廠生產好的Bean
	private final Map<String, Object> earlySingletonObjects =
			new HashMap<>(16);

	// 存放正在初始化的Bean,對象還沒有被實例化之前就放進來了
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	public  <T> T getBean(Class<T> beanClass) throws Exception {
		// 類名為Bean的名字
		String beanName = beanClass.getSimpleName();
		// 已經初始化好了,或者正在初始化
		Object initObj = getSingleton(beanName, true);
		if (initObj != null) {
			return (T) initObj;
		}
		// bean正在被初始化
		singletonsCurrentlyInCreation.add(beanName);
		// 實例化bean
		Object object = beanClass.getDeclaredConstructor().newInstance();
		singletonFactories.put(beanName, () -> {
			return object;
		});
		// 開始初始化bean,即填充屬性
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			// 獲取需要注入字段的class
			Class<?> fieldClass = field.getType();
			field.set(object, getBean(fieldClass));
		}
		singletonObjects.put(beanName, object);
		singletonsCurrentlyInCreation.remove(beanName);
		earlySingletonObjects.remove(beanName);
		return (T) object;
	}

	/**
	 * allowEarlyReference參數的含義是Spring是否允許循環依賴,默認為true
	 */
	public Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null
				&& isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory =
							this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
}

我們寫的getSingleton的實現和org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)的實現一模一樣,這個方法幾乎所有分析Spring循環依賴的文章都會提到,這次你明白工作原理是什麼了把

總結一波

  1. 拿bean的時候先從singletonObjects(一級緩存)中獲取
  2. 如果獲取不到,並且對象正在創建中,就從earlySingletonObjects(二級緩存)中獲取
  3. 如果還是獲取不到就從singletonFactories(三級緩存)中獲取,然後將獲取到的對象放到earlySingletonObjects(二級緩存)中,並且將bean對應的singletonFactories(三級緩存)清除
  4. bean初始化完畢,放到singletonObjects(一級緩存)中,將bean對應的earlySingletonObjects(二級緩存)清除

歡迎關注

參考博客

[1]https://mp.weixin.qq.com/s/gBr3UfC1HRcw4U-ZMmtRaQ
[2]https://mp.weixin.qq.com/s/5mwkgJB7GyLdKDgzijyvXw
比較詳細
[1]https://zhuanlan.zhihu.com/p/84267654
[2]https://juejin.im/post/5c98a7b4f265da60ee12e9b2

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

門多西諾複合大火續燒 面積相當於洛杉磯市

摘錄自2018年8月8日中央通訊社台北報導

美國加州野火繼續傳出災情,「門多西諾複合大火」延燒面積已相當於整個洛杉磯市,上萬名消防員今天仍不斷努力救災控制火勢,上月爆發的一連串野火已造成11人喪命。

加州北部的門多西諾複合大火(Mendocino Complex Fire)由2個分別名為「河流」(River fire)及「牧場」(Ranch fire)的野火組成,延燒面積已達29萬英畝(11萬7359公頃),大小相當於整個洛杉磯市。

門多西諾複合大火昨天(7日)改寫短短8個月前「湯瑪斯野火」(Thomas Fire)紀錄,成為加州有紀錄以來最大野火。湯瑪斯野火去年12月在南加州肆虐,延燒面積達28萬1893英畝。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

SourceTree使用詳解(連接遠程倉庫,克隆,拉取,提交,推送,新建/切換/合併分支,衝突解決)

前言:

  俗話說的好工欲善其事必先利其器,Git分佈式版本控制系統是我們日常開發中不可或缺的。目前市面上比較流行的Git可視化管理工具有SourceTree、Github Desktop、TortoiseGit,綜合網上的一些文章分析和自己的日常開發實踐心得個人比較推薦開發者使用SourceTree,因為SourceTree同時支持Windows和Mac,並且界面十分的精美簡潔,大大的簡化了開發者與代碼庫之間的Git操作方式。該篇文章主要是對日常開發中使用SourceTree可視化管理工具的一些常用操作進行詳細講解。

SourceTree | Github Desktop | TortoiseGit 可視化管理工具對比:

  https://blog.csdn.net/hmllittlekoi/article/details/104504406/

SourceTree介紹和Atlassian賬號註冊和登錄教程:

https://www.cnblogs.com/Can-daydayup/p/13128511.html

連接Gitee or GitHub,獲取代碼:

注意:這裏介紹的是使用SSH協議獲取關聯遠程倉庫的代碼,大家也可以直接使用過HTTPS協議的方式直接輸入賬號密碼獲取關聯代碼!

全面概述Gitee和GitHub生成/添加SSH公鑰:

https://www.cnblogs.com/Can-daydayup/p/13063280.html

在SourceTree中添加SSH密鑰:

工具=>選擇:

   
添加SSH密鑰位置:C:\Users\xxxxx\.ssh\id_rsa.pub:

SSH客戶端選擇OpenSSH:

 

Clone對應託管平台倉庫(以Gitee為例):

打開碼雲,找到自己需要Clone的倉庫!

 

 

SourceTree設置默認工作目錄:

  由上面我們可以發現每次Clone克隆項目的時候,克隆下來的項目默認存儲位置都是在C盤,因此每次都需要我們去選擇項目存放的路徑,作為一個喜歡偷懶的人而言當然不喜歡這種方式啦,因此我們可以設置一個默認的項目存儲位置。

設置SourceTree默認項目目錄:

點擊工具=>選項=>一般=>找到項目目錄設置Clone項目默認存儲的位置  

SourceTree代碼提交:

1.首先切換到需要修改功能代碼所在的分支:

 

 

2.將修改的代碼提交到暫存區:

3.將暫存區中的代碼提交到本地代碼倉庫:

注意:多人同時開發項目的時候,不推薦默認選中立即推送變更到origin/develop,避免一些不必要的麻煩!

 4.代碼拉取更新本地代碼庫,並將代碼推送到遠程倉庫:

 
 勾選需要推送的分支,點擊推送到遠程分支:  
代碼成功推送到遠程代碼庫:

5.在Gitee中查看推送結果:

SourceTree分支切換,新建,合併:

1.分支切換:

雙擊切換:   單擊鼠標右鍵切換:

2.新建分支:

注意:在新建分支時,我們需要在哪個主分支的基礎上新建分支必須先要切換到對應的主分支才能到該主分支上創建分支,如下我們要在master分支上創建一個feature-0613分支:  

3.合併分支:

注意:在合併代碼之前我們都需要將需要合併的分支拉取到最新狀態(**避免覆蓋別人的代碼,或者丟失一些重要文件)!!!!!   在master分支上點擊右鍵,選擇合併feature-0613至當前分支即可進行合併:   分支合併成功:

SourceTree代碼衝突解決:

首先我們需要製造一個提交文件遇到衝突的情景:

在SoureceTree中在Clone一個新項目,命名為pingrixuexilianxi2,如下圖所示:

 

 

我們以項目中的【代碼合併衝突測試.txt】文件為例:   在pingrixuexilianxi2中添加內容,並提交到遠程代碼庫,添加的內容如下:   在pingrixuexilianxi中添加內容,提交代碼(不選擇立即推送變更到origin/master),拉取代碼即會遇到衝突:  

 

 

  衝突文件中的內容:  

直接打開衝突文件手動解決衝突:

由下面的衝突文件中的衝突內容我們了解到:

<<<<<<< HEAD
6月19日 pingrixuexilianxi添加了內容
=======
6月18日 pingrixuexilianxi2修改了這個文件哦
>>>>>>> a8284fd41903c54212d1105a6feb6c57292e07b5

  <<<<<<< HEAD到 =======裏面的【6月19日 pingrixuexilianxi添加了內容】是自己剛才的Commit提交的內容 =======到 >>>>>>> a8284fd41903c54212d1105a6feb6c57292e07b5裏面的【6月18日 pingrixuexilianxi2修改了這個文件哦】是遠程代碼庫更新的內容(即為pingrixuexilianxi2本地代碼庫推送修改內容)。   手動衝突解決方法:

  根據項目需求刪除不需要的代碼就行了,假如都需要的話我們只需要把 <<<<<<< HEAD=======     >>>>>>> a8284fd41903c54212d1105a6feb6c57292e07b5都刪掉衝突就解決了(注意,在項目中最後這些符號都不能存在,否則可能會報異常)。

  最後將衝突文件標記為已解決,提交到遠程倉庫:  

採用外部文本文件對比工具Beyond Compare解決衝突:

SourceTree配置文本文件對比工具Beyond Compare:

工具=>選項=>比較:  

 

使用Beyond Compare解決衝突:

Beyond Compare使用技巧: 官方全面教程: https://www.beyondcompare.cc/jiqiao/   SourceTree打開外部和合併工具:

 

注意:第一次啟動Beynod Compare軟件需要一會時間,請耐心等待:
    Beynod Compare進行衝突合併:   點擊保存文件后關閉Beynod Compare工具,SourceTree中的衝突就解決了,在SourceTree中我們會發現多了一個 .orig 的文件。接着選中那個.orig文件,單擊右鍵 => 移除,最後我們推送到遠程代碼庫即可:  

Sourcetree中的基本名詞說明:

克隆/新建(clone):從遠程倉庫URL加載創建一個與遠程倉庫一樣的本地倉庫。 提交(commit):將暫存區文件上傳到本地代碼倉庫。
推送(push):將本地倉庫同步至遠程倉庫,一般推送(push)前先拉取(pull)一次,確保一致(十分注意:這樣你才能達到和別人最新代碼同步的狀態,同時也能夠規避很多不必要的問題)。 拉取(pull):從遠程倉庫獲取信息並同步至本地倉庫,並且自動執行合併(merge)操作(git pull=git fetch+git merge)。 獲取(fetch):從遠程倉庫獲取信息並同步至本地倉庫。 分支(branch):創建/修改/刪除分枝。 合併(merge):將多個同名文件合併為一個文件,該文件包含多個同名文件的所有內容,相同內容抵消。 貯藏(git stash):保存工作現場。 丟棄(Discard):丟棄更改,恢復文件改動/重置所有改動,即將已暫存的文件丟回未暫存的文件。 標籤(tag):給項目增添標籤。 工作流(Git Flow):團隊工作時,每個人創建屬於自己的分枝(branch),確定無誤后提交到master分支。 終端(terminal):可以輸入git命令行。 每次拉取和推送的時候不用每次輸入密碼的命令行:git config credential.helper osxkeychain sourcetree。 檢出(checkout):切換不同分支。 添加(add):添加文件到緩存區。 移除(remove):移除文件至緩存區。 重置(reset):回到最近添加(add)/提交(commit)狀態。

Git分佈式版本控制器常用命令和使用:

當然作為一個有逼格的程序員, 一些常用的命令我們還是需要了解和掌握的,詳情可參考我之前寫過的文章:

https://www.cnblogs.com/Can-daydayup/p/10134733.html

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?