現代汽車:2018冬奧推新款燃料電池車

韓國現代汽車集團宣布,將在2018年的平昌冬季奧運會之際,發表全新款的燃料電池電動車。

媒體報導,現代汽車認為冬奧是展現新技術的最佳場域,因此決定趁2018冬奧機會,推出全新的燃料電池車產品。現代汽車集團環保發展部門主任Ahn Byung-ki表示,新車的尺寸介於CUV與SUV之間,將採用更小、更輕的電池和馬達,但馬力會更高。

市場普遍認為,這款汽車將先以概念車的形式於2018年展現於世人眼前,最快要到2020年才會有量產車型上市。

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

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

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

全球電動車市場加溫 鋰電池原料價格飆漲

根據 《日本經濟新聞》 的報導,由於全世界快速發展環保電動車產業的緣故,使得電動車中重要的零組件-鋰電池,其主要的元素稀有金屬 「鋰」,1 年來的國際價格急劇上漲,僅短短1 年的時間,「鋰」 的價格就暴漲3 倍。不但,使得全球主要供應商開啟新產線,以滿足市場的需求之外,預估供給不足的情況也將持續到2019 至2020 年後。

報導中指出,稀有金屬 「鋰」 被廣泛用於生産環保車的充電電池。由於全球性的電動環保車增産,因此針對環保車電池的需求急劇增加。隨著國際 「鋰」 價格的高漲,包括以生產電動環保車電池為主的日本市場,其國內交易價格也呈上漲態勢。

報導中分析,從「鋰」的消費量觀察,中國佔全球市場的40% ,為世界最大需求國。這也使得中國國內的 「鋰」 現貨價格成為國際價格指標之一。這一現貨價格在2016 年初小幅下跌之後就一路大漲,到7 月中旬的價格為1 噸人民幣12.9 萬元左右(折合新台幣約61.43 萬元),達到1 年前價格的3 倍。

至於,中國的 「鋰」 需求量的快速增加,則是反映了中國為了改善日益嚴重的空氣污染,正加快普及純電動汽車 (EV) 和插電式混合動力車 (PHV) 的趨勢。除了消費者購買電動環保車可獲得政府補貼之外,政府還積極推廣搭載鋰電池公共汽車,這使得中國車載電池需要的 「鋰」 採購量因此大幅增加。

而除了中國之外,美國電動車廠商特斯拉 (TESLA) 的需求成長,也是 「鋰」 價格高漲的原因之一。日前,TESLA 預定於2017 年供貨的 「Model3」 電動車預售熱絡,造成鋰電池供應不足的情況。目前,為TESLA 供應車載電池的松下 (Panasonic) ,日前決定提前啟動與TESLA 在美國設立的車載電池工廠生産,計劃在2016 年底前啟動量産。

目前,「鋰」 供不應求的狀況,也使得 「鋰」 的主要供應商智利的SQM 、美國FMC 、美國雅保化工 (Albemarle) ,以及一部分中國企業開始計劃今後在北美和澳大利亞等地新設生産線。不過,即使如此,仍有不少業界人士認為,供給不足的狀況也將持續到2019 至2020 年。

根據統計,2015 年全球的「鋰」(以碳酸鋰來換算)總需求為17 萬噸。其中,鋰電池的生產需求6 萬噸。預計到2020 年時,全球總需求將提高至28 萬噸,而針對鋰電池的生產需求,將增加到16.5 萬噸。

根據日本獨立行政法人 「石油天然氣金屬礦物資源機構」(JOGMEC) 統計,在電池成本中,「鋰」 僅佔不到10% 。因此,對最終産品價格的影響有限。在日本國內,目前鋰電池的主要材料廠商尚未能徹底將原料價格的上漲轉嫁到産品價格中。不過,除鋰電池以外的工業用途,「鋰」 目前也正陷入短缺的情況。未來的價格波動,恐將在所難免。

(本文授權轉載自《》──〈〉)

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

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

比亞迪斥資110億元 擴充電池產能/推新車

據比亞迪官方獲悉,比亞迪將投入人民幣110億元對旗下兩家子公司進行增資。本次增資將用於對比亞迪汽車工業有限公司和鐵動力離子電池擴產項目,未來電池產能有望得到擴充,並將加速新能源車型的研發進度。  
  隨著資金的引入,比亞迪在新車研發速度也將加快。根據規劃,比亞迪首款以中國古朝代命名的新能源MPV—商雙模版將於今年下半年發佈並上市。此外,宋雙模版、純電動版以及一款名為M5的全新車型也將於今年下半年上市。   除上述建設專案外,基於青海豐富的鋰資源,比亞迪將于青海投資建立新電池工廠。而與青海的合作也意味著比亞迪切入產業鏈上游,有利於其在新能源汽車領域的佈局和規劃,實現資源分享。   文章來源:網通社

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

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

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

電動車供應鏈需求強,台達電、貿聯-KY忙翻

美國電動車廠商特斯拉(Tesla)、德國BMW接連提高電動車零組件的訂單,使中上游供應鏈廠商忙著接單。台灣台達電、貿聯-KY等特斯拉供貨廠商表示接單狀況良好,而台達電也透露可望與BMW達成供貨合約。

《經濟日報》報導,各國積極發展電動車,帶動了電動車產業鏈的興盛。台達電已通過歐、美、日、中等地的電動車認證標準,目前已有歐美合作廠商,未來在電動車業界的發展可期。由於台達電將於第三季起出貨北美油電混和車所需的零組件,因此台達電第三季的獲利十分看好。

在與特斯拉的合作方面,台達電一直都是Model S、Model X的電力控制系統、電池管理系統的供應商。針對特斯拉所提高的訂單需求,據了解,特斯拉已要求台達電備妥目前三至五倍的產能。另一家台系上游廠商貿聯-KY也接訂單忙翻天。

而在與BMW的合作方面,BMW將在泰國投資20億泰銖興建電動車用電池工廠,最快在2017年中動工。報導指出,台達電已與BMW達成共識,未來將為BMW供應電源控制系統,主要市場為東協。

台達電董事長海英俊曾於法說會上表示,汽車產業對台達電而言十分重要,也看好未來汽車相關應用的發展。

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

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

賓士將推出四款電動車與特斯拉競爭

今年7月,有梅賽德斯•賓士內部員工透露,該公司將於九月份發佈一款概念版的電動車與特斯拉競爭。而今天看來,梅賽德斯•賓士的計畫遠不止這些。  
  根據外媒最新消息,梅賽德斯•賓士不會僅僅局限於一兩款產品,賓士計畫推出四款電動汽車產品,希望能夠與特斯拉、寶馬等對手進行正面競爭,同時這四款電動汽車將會採用全新的命名方式。   根據梅賽德斯•賓士執行董事長Dieter Zetsche表示,第一款電動汽車將會在今年10月的巴黎車展上亮相,同時另外還有三款其它類型的產品,一共包括了兩款電動轎車和兩款電動SUV,並且預計在2020年之前陸續上市。而在今年的巴黎車展上我們將看到一款SUV產品,並且續航里程將會達到讓人印象深刻的500公里。而這輛賓士的電動SUV除了擁有強悍的續航里程之外,還將與特斯拉的Model X直接競爭。   文章來源:雷鋒網

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

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

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

[ch02-00] 反向傳播與梯度下降的通俗解釋

系列博客,原文在筆者所維護的github上:,
點擊star加星不要吝嗇,星越多筆者越努力。

第2章 神經網絡中的三個基本概念

2.0 通俗地理解三大概念

這三大概念是:反向傳播,梯度下降,損失函數。

神經網絡訓練的最基本的思想就是:先“猜”一個結果,我們叫預測結果a,看看這個預測結果和事先標記好的訓練集中的真實結果y之間的差距,然後調整策略,再試一次,這一次就不是“猜”了,而是有依據地向正確的方向靠近。如此反覆多次,一直到預測結果和真實結果之間相差無幾,亦即|a-y|->0,就結束訓練。

在神經網絡訓練中,我們把“猜”叫做初始化,可以隨機,也可以根據以前的經驗給定初始值。即使是“猜”,也是有技術含量的。

這三個概念是前後緊密相連的,講到一個,肯定會牽涉到另外一個。但由於損失函數篇幅較大,我們將在下一章中再詳細介紹。

下面我們舉幾個例子來直觀的說明下這三個概念。

2.0.1 例一:猜數

甲乙兩個人玩兒猜數的遊戲,数字的範圍是[1,50]:

甲:我猜5

乙:太小了

甲:50

乙:有點兒大

甲:30

乙:小了

……

在這個遊戲里:

  • 目的:猜到乙心中的数字;
  • 初始化:甲猜5;
  • 前向計算:甲每次猜的新数字;
  • 損失函數:乙在根據甲猜的數來和自己心中想的數做比較,得出“大了”或“小了”的結論;
  • 反向傳播:乙告訴甲“小了”、“大了”;
  • 梯度下降:甲根據乙的反饋中的含義自行調整下一輪的猜測值。

這裏的損失函數是什麼呢?就是“太小了”,“有點兒大”,很不精確!這個“所謂的”損失函數給出了兩個信息:

  1. 方向:大了或小了
  2. 程度:“太”,“有點兒”,但是很模糊

2.0.2 例二:黑盒子

假設有一個黑盒子如圖2-1。

圖2-1 黑盒子

我們只能看到輸入和輸出的數值,看不到裏面的樣子,當輸入1時,輸出2.334,然後黑盒子有個信息显示:我需要輸出值是4。然後我們試了試輸入2,結果輸出5.332,一下子比4大了很多。那麼我們第一次的損失值是\(2.334-4=-1.666\),而二次的損失值是\(5.332-4=1.332\)

這裏,我們的損失函數就是一個簡單的減法,用實際值減去目標值,但是它可以告訴你兩個信息:1)方向,是大了還是小了;2)差值,是0.1還是1.1。這樣就給了我們下一次猜的依據。

  • 目的:猜到一個輸入值,使得黑盒子的輸出是4
  • 初始化:輸入1
  • 前向計算:黑盒子內部的數學邏輯
  • 損失函數:在輸出端,用輸出值減4
  • 反向傳播:告訴猜數的人差值,包括正負號和值
  • 梯度下降:在輸入端,根據正負號和值,確定下一次的猜測值,goto前向計算

2.0.3 例三:打靶

小明拿了一支步槍,射擊100米外的靶子。這支步槍沒有準星,或者是準星有問題,或者是小明眼神兒不好看不清靶子,或者是霧很大,或者風很大,或者由於木星的影響而側向引力場異常……反正就是遇到各種干擾因素。

第一次試槍后,拉回靶子一看,彈着點偏左了,於是在第二次試槍時,小明就會有意識地向右側偏幾毫米,再看靶子上的彈着點,如此反覆幾次,小明就會掌握這支步槍的脾氣了。圖2-2显示了小明的5次試槍過程。

圖2-2 打靶的彈着點記錄

在有監督的學習中,需要衡量神經網絡輸出和所預期的輸出之間的差異大小。這種誤差函數需要能夠反映出當前網絡輸出和實際結果之間一種量化之後的不一致程度,也就是說函數值越大,反映出模型預測的結果越不準確。

這個例子中,小明預期的目標是全部命中靶子的中心,最外圈是1分,之後越向靶子中心分數是2,3,4分,正中靶心可以得10分。

  • 每次試槍彈着點和靶心之間的差距就叫做誤差,可以用一個誤差函數來表示,比如差距的絕對值,如圖中的紅色線。
  • 一共試槍5次,就是迭代/訓練了5次的過程 。
  • 每次試槍后,把靶子拉回來看彈着點,然後調整下一次的射擊角度的過程,叫做反向傳播。注意,把靶子拉回來看和跑到靶子前面去看有本質的區別,後者容易有生命危險,因為還有別的射擊者。一個不恰當的比喻是,在數學概念中,人跑到靶子前面去看,叫做正向微分;把靶子拉回來看,叫做反向微分。
  • 每次調整角度的數值和方向,叫做梯度。比如向右側調整1毫米,或者向左下方調整2毫米。如圖中的綠色矢量線。

上圖是每次單發點射,所以每次訓練樣本的個數是1。在實際的神經網絡訓練中,通常需要多個樣本,做批量訓練,以避免單個樣本本身採樣時帶來的誤差。在本例中,多個樣本可以描述為連發射擊,假設一次可以連打3發子彈,每次的離散程度都類似,如圖2-3所示。

圖2-3 連發彈着點記錄

  • 如果每次3發子彈連發,這3發子彈的彈着點和靶心之間的差距之和再除以3,叫做損失,可以用損失函數來表示。

那小明每次射擊結果和目標之間的差距是多少呢?在這個例子裏面,用得分來衡量的話,就是說小明得到的反饋結果從差9分,到差8分,到差2分,到差1分,到差0分,這就是用一種量化的結果來表示小明的射擊結果和目標之間差距的方式。也就是誤差函數的作用。因為是一次只有一個樣本,所以這裏採用的是誤差函數的稱呼。如果一次有多個樣本,就要叫做損失函數了。

其實射擊還不這麼簡單,如果是遠距離狙擊,還要考慮空氣阻力和風速,在神經網絡里,空氣阻力和風速可以對應到隱藏層的概念上。

在這個例子中:

  • 目的:打中靶心;
  • 初始化:隨便打一槍,能上靶就行,但是要記住當時的步槍的姿態;
  • 前向計算:讓子彈飛一會兒,擊中靶子;
  • 損失函數:環數,偏離角度;
  • 反向傳播:把靶子拉回來看;
  • 梯度下降:根據本次的偏差,調整步槍的射擊角度,goto前向計算。

損失函數的描述是這樣的:

  1. 1環,偏左上45度;
  2. 6環,偏左上15度;
  3. 7環,偏左;
  4. 8環,偏左下15度;
  5. 10環。

這裏的損失函數也有兩個信息:

  1. 距離;
  2. 方向。

所以,梯度,是個矢量! 它應該即告訴我們方向,又告訴我們數值。

2.0.4 黑盒子的真正玩兒法

以上三個例子比較簡單,容易理解,我們把黑盒子再請出來:黑盒子這件事真正的意義並不是猜測當輸入是多少時輸出會是4。它的實際意義是:我們要破解這個黑盒子!於是,我們會有如下破解流程:

  1. 記錄下所有輸入值和輸出值,如表2-1。

表2-1 樣本數據表

樣本ID 輸入(特徵值) 輸出(標籤)
1 1 2.21
2 1.1 2.431
3 1.2 2.652
4 2 4.42
  1. 搭建一個神經網絡,給出初始權重值,我們先假設這個黑盒子的邏輯是:\(z=x + x^2\)
  2. 輸入1,根據\(z=x + x^2\)得到輸出為2,而實際的輸出值是2.21,則誤差值為\(2-2.21=-0.21\),小了;
  3. 調整權重值,比如\(z=1.5x+x^2\),再輸入1.1,得到的輸出為2.86,實際輸出為2.431,則誤差值為\(2.86-2.431=0.429\),大了;
  4. 調整權重值,比如\(z=1.2x+x^2\)再輸入1.2……
  5. 調整權重值,再輸入2……
  6. 所有樣本遍歷一遍,計算平均的損失函數值;
  7. 依此類推,重複3,4,5,6過程,直到損失函數值小於一個指標,比如0.001,我們就可以認為網絡訓練完畢,黑盒子“破解”了,實際是被複制了,因為神經網絡並不能得到黑盒子里的真實函數體,而只是近似模擬。

從上面的過程可以看出,如果誤差值是正數,我們就把權重降低一些;如果誤差值為負數,則升高權重。

2.0.5 總結

簡單總結一下反向傳播與梯度下降的基本工作原理:

  1. 初始化;
  2. 正向計算;
  3. 損失函數為我們提供了計算損失的方法;
  4. 梯度下降是在損失函數基礎上向著損失最小的點靠近而指引了網絡權重調整的方向;
  5. 反向傳播把損失值反向傳給神經網絡的每一層,讓每一層都根據損失值反向調整權重;
  6. goto 2,直到精度足夠好(比如損失函數值小於0.001)。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

Kotlin Coroutines不複雜, 我來幫你理一理

Coroutines 協程

最近在總結Kotlin的一些東西, 發現協程這塊確實不容易說清楚. 之前的那篇就寫得不好, 所以決定重寫.
反覆研究了官網文檔和各種教程博客, 本篇內容是最基礎也最主要的內容, 力求小白也能看懂並理解.

Coroutines概念

Coroutines(協程), 計算機程序組件, 通過允許任務掛起和恢復執行, 來支持非搶佔式的多任務. (見).

協程主要是為了異步, 非阻塞的代碼. 這個概念並不是Kotlin特有的, Go, Python等多個語言中都有支持.

Kotlin Coroutines

Kotlin中用協程來做異步和非阻塞任務, 主要優點是代碼可讀性好, 不用回調函數. (用協程寫的異步代碼乍一看很像同步代碼.)

Kotlin對協程的支持是在語言級別的, 在標準庫中只提供了最低程度的APIs, 然後把很多功能都代理到庫中.

Kotlin中只加了suspend作為關鍵字.
asyncawait不是Kotlin的關鍵字, 也不是標準庫的一部分.

比起futures和promises, kotlin中suspending function的概念為異步操作提供了一種更安全和不易出錯的抽象.

kotlinx.coroutines是協程的庫, 為了使用它的核心功能, 項目需要增加kotlinx-coroutines-core的依賴.

Coroutines Basics: 協程到底是什麼?

先上一段官方的demo:

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


fun main() {
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

這段代碼的輸出:
先打印Hello, 延遲1s之後, 打印World.

對這段代碼的解釋:

launch開始了一個計算, 這個計算是可掛起的(suspendable), 它在計算過程中, 釋放了底層的線程, 當協程執行完成, 就會恢復(resume).

這種可掛起的計算就叫做一個協程(coroutine). 所以我們可以簡單地說launch開始了一個新的協程.

注意, 主線程需要等待協程結束, 如果註釋掉最後一行的Thread.sleep(2000L), 則只打印Hello, 沒有World.

協程和線程的關係

coroutine(協程)可以理解為輕量級的線程. 多個協程可以并行運行, 互相等待, 互相通信. 協程和線程的最大區別就是協程非常輕量(cheap), 我們可以創建成千上萬個協程而不必考慮性能.

協程是運行在線程上可以被掛起的運算. 可以被掛起, 意味着運算可以被暫停, 從線程移除, 存儲在內存里. 此時, 線程就可以自由做其他事情. 當計算準備好繼續進行時, 它會返回線程(但不一定要是同一個線程).

默認情況下, 協程運行在一個共享的線程池裡, 線程還是存在的, 只是一個線程可以運行多個協程, 所以線程沒必要太多.

調試

在上面的代碼中加上線程的名字:

fun main() {
    GlobalScope.launch {
        // launch a new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World! + ${Thread.currentThread().name}") // print after delay
    }
    println("Hello, + ${Thread.currentThread().name}") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

可以在IDE的Edit Configurations中設置VM options: -Dkotlinx.coroutines.debug, 運行程序, 會在log中打印出代碼運行的協程信息:

Hello, + main
World! + DefaultDispatcher-worker-1 @coroutine#1

suspend function

上面例子中的delay方法是一個suspend function.
delay()Thread.sleep()的區別是: delay()方法可以在不阻塞線程的情況下延遲協程. (It doesn’t block a thread, but only suspends the coroutine itself). 而Thread.sleep()則阻塞了當前線程.

所以, suspend的意思就是協程作用域被掛起了, 但是當前線程中協程作用域之外的代碼不被阻塞.

如果把GlobalScope.launch替換為thread, delay方法下面會出現紅線報錯:

Suspend functions are only allowed to be called from a coroutine or another suspend function

suspend方法只能在協程或者另一個suspend方法中被調用.

在協程等待的過程中, 線程會返回線程池, 當協程等待結束, 協程會在線程池中一個空閑的線程上恢復. (The thread is returned to the pool while the coroutine is waiting, and when the waiting is done, the coroutine resumes on a free thread in the pool.)

啟動協程

啟動一個新的協程, 常用的主要有以下幾種方式:

  • launch
  • async
  • runBlocking

它們被稱為coroutine builders. 不同的庫可以定義其他更多的構建方式.

runBlocking: 連接blocking和non-blocking的世界

runBlocking用來連接阻塞和非阻塞的世界.

runBlocking可以建立一個阻塞當前線程的協程. 所以它主要被用來在main函數中或者測試中使用, 作為連接函數.

比如前面的例子可以改寫成:

fun main() = runBlocking<Unit> {
    // start main coroutine
    GlobalScope.launch {
        // launch a new coroutine in background and continue
        delay(1000L)
        println("World! + ${Thread.currentThread().name}")
    }
    println("Hello, + ${Thread.currentThread().name}") // main coroutine continues here immediately
    delay(2000L) // delaying for 2 seconds to keep JVM alive
}

最後不再使用Thread.sleep(), 使用delay()就可以了.
程序輸出:

Hello, + main @coroutine#1
World! + DefaultDispatcher-worker-1 @coroutine#2

launch: 返回Job

上面的例子delay了一段時間來等待一個協程結束, 不是一個好的方法.

launch返回Job, 代表一個協程, 我們可以用Jobjoin()方法來顯式地等待這個協程結束:

fun main() = runBlocking {
    val job = GlobalScope.launch {
        // launch a new coroutine and keep a reference to its Job
        delay(1000L)
        println("World! + ${Thread.currentThread().name}")
    }
    println("Hello, + ${Thread.currentThread().name}")
    job.join() // wait until child coroutine completes
}

輸出結果和上面是一樣的.

Job還有一個重要的用途是cancel(), 用於取消不再需要的協程任務.

async: 從協程返回值

async開啟線程, 返回Deferred<T>, Deferred<T>Job的子類, 有一個await()函數, 可以返回協程的結果.

await()也是suspend函數, 只能在協程之內調用.

fun main() = runBlocking {
    // @coroutine#1
    println(Thread.currentThread().name)
    val deferred: Deferred<Int> = async {
        // @coroutine#2
        loadData()
    }
    println("waiting..." + Thread.currentThread().name)
    println(deferred.await()) // suspend @coroutine#1
}

suspend fun loadData(): Int {
    println("loading..." + Thread.currentThread().name)
    delay(1000L) // suspend @coroutine#2
    println("loaded!" + Thread.currentThread().name)
    return 42
}

運行結果:

main @coroutine#1
waiting...main @coroutine#1
loading...main @coroutine#2
loaded!main @coroutine#2
42

Context, Dispatcher和Scope

看一下launch方法的聲明:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
...
}

其中有幾個相關概念我們要了解一下.

協程總是在一個context下運行, 類型是接口CoroutineContext. 協程的context是一個索引集合, 其中包含各種元素, 重要元素就有Job和dispatcher. Job代表了這個協程, 那麼dispatcher是做什麼的呢?

構建協程的coroutine builder: launch, async, 都是CoroutineScope類型的擴展方法. 查看CoroutineScope接口, 其中含有CoroutineContext的引用. scope是什麼? 有什麼作用呢?

下面我們就來回答這些問題.

Dispatchers和線程

Context中的CoroutineDispatcher可以指定協程運行在什麼線程上. 可以是一個指定的線程, 線程池, 或者不限.

看一個例子:

fun main() = runBlocking<Unit> {
    launch {
        // context of the parent, main runBlocking coroutine
        println("main runBlocking      : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(Dispatchers.Unconfined) {
        // not confined -- will work with main thread
        println("Unconfined            : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(Dispatchers.Default) {
        // will get dispatched to DefaultDispatcher
        println("Default               : I'm working in thread ${Thread.currentThread().name}")
    }
    launch(newSingleThreadContext("MyOwnThread")) {
        // will get its own new thread
        println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
    }
}

運行后打印出:

Unconfined            : I'm working in thread main
Default               : I'm working in thread DefaultDispatcher-worker-1
newSingleThreadContext: I'm working in thread MyOwnThread
main runBlocking      : I'm working in thread main

API提供了幾種選項:

  • Dispatchers.Default代表使用JVM上的共享線程池, 其大小由CPU核數決定, 不過即便是單核也有兩個線程. 通常用來做CPU密集型工作, 比如排序或複雜計算等.
  • Dispatchers.Main指定主線程, 用來做UI更新相關的事情. (需要添加依賴, 比如kotlinx-coroutines-android.) 如果我們在主線程上啟動一個新的協程時, 主線程忙碌, 這個協程也會被掛起, 僅當線程有空時會被恢復執行.
  • Dispatchers.IO: 採用on-demand創建的線程池, 用於網絡或者是讀寫文件的工作.
  • Dispatchers.Unconfined: 不指定特定線程, 這是一個特殊的dispatcher.

如果不明確指定dispatcher, 協程將會繼承它被啟動的那個scope的context(其中包含了dispatcher).

在實踐中, 更推薦使用外部scope的dispatcher, 由調用方決定上下文. 這樣也方便測試.

newSingleThreadContext創建了一個線程來跑協程, 一個專註的線程算是一種昂貴的資源, 在實際的應用中需要被釋放或者存儲復用.

切換線程還可以用withContext, 可以在指定的協程context下運行代碼, 掛起直到它結束, 返回結果.
另一種方式是新啟一個協程, 然後用join明確地掛起等待.

在Android這種UI應用中, 比較常見的做法是, 頂部協程用CoroutineDispatchers.Main, 當需要在別的線程上做一些事情的時候, 再明確指定一個不同的dispatcher.

Scope是什麼?

launch, asyncrunBlocking開啟新協程的時候, 它們自動創建相應的scope. 所有的這些方法都有一個帶receiver的lambda參數, 默認的receiver類型是CoroutineScope.

IDE會提示this: CoroutineScope:

launch { /* this: CoroutineScope */
}

當我們在runBlocking, launch, 或async的大括號裏面再創建一個新的協程的時候, 自動就在這個scope里創建:

fun main() = runBlocking {
    /* this: CoroutineScope */
    launch { /* ... */ }
    // the same as:
    this.launch { /* ... */ }
}

因為launch是一個擴展方法, 所以上面例子中默認的receiver是this.
這個例子中launch所啟動的協程被稱作外部協程(runBlocking啟動的協程)的child. 這種”parent-child”的關係通過scope傳遞: child在parent的scope中啟動.

協程的父子關係:

  • 當一個協程在另一個協程的scope中被啟動時, 自動繼承其context, 並且新協程的Job會作為父協程Job的child.

所以, 關於scope目前有兩個關鍵知識點:

  • 我們開啟一個協程的時候, 總是在一個CoroutineScope里.
  • Scope用來管理不同協程之間的父子關係和結構.

協程的父子關係有以下兩個特性:

  • 父協程被取消時, 所有的子協程都被取消.
  • 父協程永遠會等待所有的子協程結束.

值得注意的是, 也可以不啟動協程就創建一個新的scope. 創建scope可以用工廠方法: MainScope()CoroutineScope().

coroutineScope()方法也可以創建scope. 當我們需要以結構化的方式在suspend函數內部啟動新的協程, 我們創建的新的scope, 自動成為suspend函數被調用的外部scope的child.

上面的父子關係, 可以進一步抽象到, 沒有parent協程, 由scope來管理其中所有的子協程.

Scope在實際應用中解決什麼問題呢? 如果我們的應用中, 有一個對象是有自己的生命周期的, 但是這個對象又不是協程, 比如Android應用中的Activity, 其中啟動了一些協程來做異步操作, 更新數據等, 當Activity被銷毀的時候需要取消所有的協程, 來避免內存泄漏. 我們就可以利用CoroutineScope來做這件事: 創建一個CoroutineScope對象和activity的生命周期綁定, 或者讓activity實現CoroutineScope接口.

所以, scope的主要作用就是記錄所有的協程, 並且可以取消它們.

A CoroutineScope keeps track of all your coroutines, and it can cancel all of the coroutines started in it.

Structured Concurrency

這種利用scope將協程結構化組織起來的機制, 被稱為”structured concurrency”.
好處是:

  • scope自動負責子協程, 子協程的生命和scope綁定.
  • scope可以自動取消所有的子協程.
  • scope自動等待所有的子協程結束. 如果scope和一個parent協程綁定, 父協程會等待這個scope中所有的子協程完成.

通過這種結構化的併發模式: 我們可以在創建top級別的協程時, 指定主要的context一次, 所有嵌套的協程會自動繼承這個context, 只在有需要的時候進行修改即可.

GlobalScope: daemon

GlobalScope啟動的協程都是獨立的, 它們的生命只受到application的限制. 即GlobalScope啟動的協程沒有parent, 和它被啟動時所在的外部的scope沒有關係.

launch(Dispatchers.Default) { ... }GlobalScope.launch { ... }用的dispatcher是一樣的.

GlobalScope啟動的協程並不會保持進程活躍. 它們就像daemon threads(守護線程)一樣, 如果JVM發現沒有其他一般的線程, 就會關閉.

參考

第三方博客:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

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

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

特斯拉、納智捷紛傳電動車失火意外

眾所矚目的電動車品牌特斯拉(Tesla)狀況不斷,先是Autopilot自動駕駛功能出包,最近又傳出車輛自燃事故。無獨有偶的,台灣的電動車品牌納智捷(Luxgen)也傳出車輛起火,引發各界的安全性關注。

外媒報導,一輛Tesla Model S 90D 在法國提供消費者試駕服務時突然傳出巨響,儀表板並顯示充電系統發生問題;在消費者與特斯拉的司機下車後,車輛即陷入火海,並很快燒個精光。由於這不是特斯拉首次發生火燒車事故,特斯拉立即表示會配合法國相關單位調查事故原因。

另一方面,位於新北市的裕隆汽車大樓於8月17日中午傳出失火意外,起火點是停放在地下室的一輛電動車,車款為LUXGEN MVP EV。據了解,該車目前僅供集團公務使用,並在特定地點供民眾租用,還沒有上市販售。裕隆汽車公關對外表示,起火前曾對該電動車進行測試,疑似車內電線走火才引發火災,將配合調查失火原因。

特斯拉車輛剛出現失火意外時,曾被懷疑是電池防護性不足的問題,因此在車底加上了防護板,但仍無法完全解決問題,甚至有充電途中起火燃燒的案例。而納智捷也被懷疑因電力系統走火而造成失火,電動車的電系零件安全性因而備受關注。

(照片:在法國起火的特斯拉電動車。來源:翻攝網路)

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

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

福斯電動原型車,將於巴黎亮相!

因排氣檢測造假而陷入醜聞風暴的德國大眾福斯集團,決定將以環保的電動車來洗刷負面形象。福斯提前了電動車生產時程,預計在2025年推出30款電動車;而第一款車款的原型車將於下個月在巴黎車展亮相。

福斯目前僅有一款電動車款──e-Golf。在爆出排氣造假事件後,福斯被強制投資20億美金,用於研發電動汽車;福斯也藉此機會加速電動車研發腳步,不僅喊出所有電動車續航力300公里以上的目標,也將研發一款MEB平台,並用MEB平台為基礎來發展電動車產品線。

福斯執行長Hebert Diess對於即將呈現在世人眼前的原型車款指出,新款電動車的大小與GOLF差不多,但將採用新的電動車底盤平台,因此空間表現將相當於Passat,續航力也可上看400公里。他也透露,這款原型車其實已相當接近可量產的版本。

此外,福斯打算在所有電動車款上都安裝60kWh以上的電池,相當於續航力290~450公里。福斯也看好電動車需求帶動的電池需求成長,因此會考慮尋找地點設置自己的電池工廠。先前福斯曾透露,中國是設置電池廠的考量地點之一。

(照片:VW e-Golf 。來源:Volkswagen )

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

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

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

中華電、e-moving跨業合作 直營門市推獨家優惠

中華電宣布,公司與電動機車龍頭中華汽車攜手合作推出「e-moving電動機車/自行車」獨家優惠,只要是中華電市內電話或寬頻的客戶,即日起於中華電直營門市即可享有優惠價,並擁有「業界最長-電池保固4年」獨家好禮。

依據環保署統計,台灣是全球機車密度最高的地區,空污問題日趨嚴重,細懸浮微粒(PM2.5)36%來自汽機車廢氣排放,有鑑於此,中華電特別響應政府節能減碳及空污管制政策,攜手中華汽車對抗PM2.5,鼓勵全民騎乘綠色交通工具e-moving,一起為環保種下幸福種籽。

中華電北區分公司總經理鄭閔卿表示,中華汽車的電動車在市場屢創佳績,深獲民眾肯定,這次很榮幸能跨業合作,由中華汽車加碼提供在公司旗下直營門市購買e-moving電動機車的客戶,除原有電池保固3年外,特別再贈送1年優惠。

中華汽車表示,旗下e-moving電動車榮獲國內外優良產品設計獎項(德國iF設計大獎),擁有44項專利,採用重機同級的「自動駐車架」,搭配「自動倒車裝置」功能,其中EM100車系更配備專屬「省力牽車」,提供輕鬆省力的代步功能,是都會女性及上班族的最愛,輕鬆優雅好停車。

中華汽車電動二輪營銷部經理黃奕元表示,電動機車不像汽油機車有複雜的零件,每二千公里只需換齒輪油,大幅節省保養費用,一般機車1元只能跑1.2公里;電動車1元可跑15公里,以每月機車平均行駛500km計算,騎e-moving一年,節能減碳效益相當於種植20顆樹。

中華電表示,在直營門市推出購車服務之後,預期市場上電動車用戶也將大幅增加,而公司亦深感榮幸,能經由本項節能商品銷售來配合政府政策,善盡企業社會責任。

(本文內容由授權提供)

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

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整