2013第五屆中國(臨沂)新能源汽車、電動車及零部件展覽會

主辦單位:中國國際貿易促進委員會臨沂市委員會、山東省環保產業協會、山東省環保產品認證中心 、臨沂市資源節約型環境友好型社會建設改革試點辦公室

承辦單位:臨沂市格益傳媒有限公司

抓住機遇2012 New energy vehicles Exhibition 激情魯南,物流業大市的優勢催生山東商業「二次飛躍」新格局2012 New energy vehicles Exhibition送給您一個千載難逢的商機!山東是國內第三大市場,臨沂是山東最重要的產品集散地,同時是國內第二大商貿城和物流之都,500公里半徑覆蓋華北市場,全國十大工業品市場中名列第三。作為魯東南中心城市,凝聚力、輻射力、帶動力逐步提升,現已成為全國繼江蘇、浙江、天津之後新崛起的電動車產業基地,山東省十大影響力產業集群。

「一年之計在於春」,由格益傳媒有限公司承辦的「第五屆中國(臨沂)新能源汽車、電動車及零部件展覽會」定於2013年4月舉行, 4月既是商家銷售產品的有利時機也是商家採購產品的旺季,同時也是廠家促銷產品、推出新品、打造品牌的最佳時機。在這個時候新能源電動車及零部件展覽會有利於促進廠商之間的交流,實現共同發展。我們誠摯的邀請廣大新能源電動汽車、電動車及零部件廠商到商貿物流城-臨沂參展、參會,共享成功展會帶來的巨大商機!

【展會日程安排】展覽時間: 2013年4月19-21日 閉幕撤展時間:2013年4月21日下午15:00
  
【參展範圍】新能源車輛展區:整 車:電動(混合動力)汽車、電動旅遊觀光車、電動高爾夫車,電動吉普車、太陽能電動車、電動客貨車、電動清潔車、電動叉車、電動升降車;氫能源、天然氣等各種新能源車輛;各種低排放、環保節能型汽車臨沂特色電動客運三輪車展區電動兩輪、三輪車展區:各類電動自行車、電動三輪車、燃油助力車及殘疾人專用電動車、電動滑板車等特種電動車特種車輛展區:清障車、環保車輛、改裝車輛等。配套電池、配件、零部件和相關技術資料展區

【收費標準】 國際標準展位:展位3m×3m 3600元 /個 國際標準展位(雙面開口) 4200元/個標準展位配套設施:三面或兩面展板、一張洽談桌、兩把椅子、兩盞射燈、一個220V的電源插座、參展單位楣板文字製作以及展館內衛生、安全保衛等。

特展:最少以36平方米起租,國內企業:400元/平方米,國外企業100美元/平方米;(註:室內空地無配套設施:展具由參展商自行設計搭建。)

【參展手續】◆填寫參展申請書,加蓋公章後郵寄或傳真至大會組委會,參展申請被接收後組委會將通過傳真或郵寄方式發放「參展確認書」確認您的申請;展位按「先報名,先分配,先付款」的原則安排。

◆申請被確認後7天內將所需費用匯入大會指定帳號,逾期不確認參展資格,展位按「先申請,先付款,先分配」的原則安排。

◆會前一個月組委會將協助參展企業完成參展後續服務。參展一經確認,參展商不得撤消參展和轉讓展位。因某種特殊原因或不可抗拒因素時,組委會有權將展期和展場更改,若因某種原因取消本次會議,參展商所交費用全部退回;

◆組委會根據現場實際情況有權對極少數參展企業的展位予以現場調整。

【展會特色及亮點】

1、通過山東省的宣傳媒體,在本地區進行密集宣傳推介;
2、各專業報刊、雜誌媒體宣傳推介本屆展會信息及互聯網推廣;
3、發函邀請各行業內專業協會、團體;並邀約海內外客商及中間商參觀;
4、山東省首家涉足新能源汽車展並連續成功舉辦四屆的專業展會;
5、山東省行業內唯一採用「大巴車免費迎接經銷商」參展模式的專業展會;
6、組委會同時組織了電動車行業發展論壇,資深業內專業人士深入探討交流;
7、組委會安排專人走訪市場並邀請安徽、江蘇、河南、河北、山東、浙江、天 津等地的電動車及零部件產業類生產企業,進一步廣泛邀請專業經銷商。
8、發函邀請友好城市政府機構、行業組織;

大會組委會聯繫方式:

聯繫人:2013第五屆中國(臨沂)新能源汽車、電動車及零部件展覽會組委會
電 話:0539-8059156 15725997759 15653999229 張經理
傳 真:0539-8059156

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

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

TT electronics推出用於混合動力汽車的大功率電阻

 

TT electronics公司推出WPRT系列線繞功率徑向端子(Wirewound Power Radial Terminal)電阻,符合AEC-Q200標準,設計用於滿足包括混合動力汽車(Hybrid Electric Vehicle, HEV)的大功率應用的特殊要求。   隨著WPRT系列的推出,TT electronics現在已提供業界最廣泛的規格和配置。新電阻系列由高純度陶瓷棒和壓配 (force-fit) 端帽(end-cap)構成,其上纏繞著導線元件,而後使用防火絕緣接合劑將其放置在陶瓷容器內,因此,在規定的溫度和超載狀況下電阻能夠完全防火。   這款電阻產品採用針對浪湧性能而優化的獨特設計,使之成為電動汽車和電機驅動的理想選擇。WPRT系列根據最高容差標準製造,可以很好地適合汽車保護裝置,大大改進了裝配性能。   TT electronics高級應用工程師 Stephen Oxley 評論說:“WPRT系列瞄準工業、汽車和能源領域的特定需求,通過開發最廣泛的此種類別功率電阻,TT electronics正在實踐承諾,不但支援客戶的節能設計,同時消除開發定制功率電阻解決方案的風險、成本和複雜性。”   WPRT系列可用於HEV預充電和BDU放電應用,以及保護電機避免浪湧電流的損壞。此外,該系列採用了浪湧保護設計,也適用於UPS系統。   WPRT系列包含了從10W至50W的六種額定功率,對於WPRT50 (50W)器件,可耐受最大250W超載。TT electronics提供的這些電阻都符合E24標準電阻值。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Tesla升級超級充電站,20分鐘獲得近200公里續航里程

美國電動跑車製造商特斯拉((Tesla Motors Inc.)近日宣布,目前正在升級其計劃覆蓋全美和加拿大部分地區的超級充電站,使電能輸出升級到120Kwh,令特斯拉電動車充電20分鐘獲得近200公里的續航里程。

據美國獨立汽車分析師SalDemir介紹,120Kwh的高壓充電樁能以比公共充電樁快16倍的速度,在30分鐘內讓車擁有320公里的續航里程。特斯拉充電站的技術升級是從端口提高電壓而非更換設備,長期來說產生的費用很小。

近日,特斯拉首席技術官JB Straubel在接受《麻省理工科技創業》採訪時表示,公司正在致力於研發將充電時間降低到5分鐘的方案。雖然1年內不太可能實現,從長期來看肯定能夠達到這個目標。

獨立汽車分析師認為,隨著技術日趨提高,充電時間逐漸接近甚至超過加油速度。從使用習慣來看,換電池計劃未來最終會消失。

特斯拉CEO Elon Musk透露,他希望讓使用非特斯拉品牌的電動車用戶能免費使用超級充電站,意味著其他汽車公司每年會向特斯拉繳納使用費,甚至幫特斯拉建設充電站。

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

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

中國南車將進軍純電動公務車領域

據中國國資委官網的消息,為響應政府公用車、公交車要率先推廣新能源汽車的號召,中國南車研制了有“陸地公務艙”之稱的純電動中型公務車。日前,由中國南車旗下南車時代電動申報的“純電動中型公務車研制”項目入選2014年度國家科技支撐計劃,成為國家級新能源中型公務車重點支持項目。

而中國南車業務一直是以鐵路機車、客車、動車組的設計、研發制造、銷售為主的,此次卻將業務范圍拓展到了電動汽車領域。

據中國南車集團公司宣傳部部長曹鋼材表示:「其實,此次已經不是中國南車第一次涉及電動汽車領域了,因為,隸屬于南車的南車株洲電力機車研究所有限公司一直在做電動汽車的研發及應用。」

據了解,高端中型公務車的年需求量在20萬輛左右,市場總額在600億元-800億元之間,市場蛋糕前景誘人,但目前大都是外資品牌。

在今年兩會期間,公務車改革呼聲十分強烈,伴隨著各級機關「厲行勤儉節約」風氣的貫徹落實以及國家公務車採購標準修訂方案的出臺實施,公務車採購自主化堅冰正在消融。7月12日,國務院總理李克強主持國務院常務會議,會議要求,政府公用車、公交車要率先推廣新能源汽車,並明確了到2015年我國大力推廣新能源公務車的目標。 

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

韓國發明可折疊電動汽車

全球不少大城市都面臨交通擁擠,停車位嚴重不足的問題。而韓國近日研發一款可折疊電動汽車,減少樂停車時佔據的空間。

據韓國科研人員介紹,這款稱為Armadillo-T的車子可搭載兩個人,最高速度為每小時60公裏,充電10分鐘可走100公裏。駕駛員還可利用智能手機應用程序,在車子外部發出折疊或展開指令。

據了解,Armadillo-T在停車時會以車體中心為軸抬起後輪,使得車子佔位長度從2.8公尺縮短到1.65公尺。一個普通停車位可放置三輛Armadillo-T汽車,而且它可在停車狀態下旋轉360度,停放在普通車輛不能停放的地方。

為安全起見,設計師還將傳統的後視鏡置替換為環繞視圖攝像頭。然而,由于Armadillo-T未達韓國公共交通安全準則,如無法承受猛烈撞擊,因此無法在街道上行駛。

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

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

江淮汽車否認與特斯拉成立合資公司

早前有證券網站的消息稱,江淮汽車擬與特斯拉在合肥成立電動汽車合資公司,項目總投資額為50億元,雙方各持50%股權。報導還稱,江淮汽車還將以幾乎全部的插電式混合動力汽車資產和業務作為出資投入合資公司,而特斯拉將以現金出資,並為合資公司提供某些工業產權。

對此,江淮董事會秘書馮梁森與特斯拉中國銷售總監沈琪都表示,並無此事。

而除了江淮,比亞迪也是特斯拉的傳聞合作對象。雖然特斯拉CEO穆斯克與比亞迪掌門王傳福互相看輕,但比亞迪得到巴菲特的垂青,業界并不排除這兩家公司的合作可能。

另外,中國的零部件供應商同樣躍躍欲試。其中,成飛集成就曾表示,會積極尋求與特斯拉的合作機會。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

TensorFlow中讀取圖像數據的三種方式

  本文面對三種常常遇到的情況,總結三種讀取數據的方式,分別用於處理單張圖片、大量圖片,和TFRecorder讀取方式。並且還補充了功能相近的tf函數。

1、處理單張圖片

  我們訓練完模型之後,常常要用圖片測試,有的時候,我們並不需要對很多圖像做測試,可能就是幾張甚至一張。這種情況下沒有必要用隊列機制。

import tensorflow as tf
import matplotlib.pyplot as plt

def read_image(file_name):
    img = tf.read_file(filename=file_name)     # 默認讀取格式為uint8
    print("img 的類型是",type(img));
    img = tf.image.decode_jpeg(img,channels=0) # channels 為1得到的是灰度圖,為0則按照圖片格式來讀
    return img

def main( ):
    with tf.device("/cpu:0"):
         # img_path是文件所在地址包括文件名稱,地址用相對地址或者絕對地址都行 
            img_path='./1.jpg'
            img=read_image(img_path)
            with tf.Session() as sess:
            image_numpy=sess.run(img)
            print(image_numpy)
            print(image_numpy.dtype)
            print(image_numpy.shape)
            plt.imshow(image_numpy)
            plt.show()

if __name__=="__main__":
    main()

"""
輸出結果為:

img 的類型是 <class 'tensorflow.python.framework.ops.Tensor'>
[[[196 219 209]
  [196 219 209]
  [196 219 209]
  ...

 [[ 71 106  42]
  [ 59  89  39]
  [ 34  63  19]
  ...
  [ 21  52  46]
  [ 15  45  43]
  [ 22  50  53]]]
uint8
(675, 1200, 3)
"""

   和tf.read_file用法相似的函數還有tf.gfile.FastGFile  tf.gfile.GFile,只是要指定讀取方式是’r’ 還是’rb’ 。

2、需要讀取大量圖像用於訓練

  這種情況就需要使用Tensorflow隊列機制。首先是獲得每張圖片的路徑,把他們都放進一個list裏面,然後用string_input_producer創建隊列,再用tf.WholeFileReader讀取。具體請看下例:

def get_image_batch(data_file,batch_size):
    data_names=[os.path.join(data_file,k) for k in os.listdir(data_file)]
 
    #這個num_epochs函數在整個Graph是local Variable,所以在sess.run全局變量的時候也要加上局部變量。  
    filenames_queue=tf.train.string_input_producer(data_names,num_epochs=50,shuffle=True,capacity=512)
    reader=tf.WholeFileReader()
    _,img_bytes=reader.read(filenames_queue)
    image=tf.image.decode_png(img_bytes,channels=1)    #讀取的是什麼格式,就decode什麼格式
    #解碼成單通道的,並且獲得的結果的shape是[?, ?,1],也就是Graph不知道圖像的大小,需要set_shape
    image.set_shape([180,180,1])   #set到原本已知圖像的大小。或者直接通過tf.image.resize_images,tf.reshape()
    image=tf.image.convert_image_dtype(image,tf.float32)
    #預處理  下面的一句代碼可以換成自己想使用的預處理方式
    #image=tf.divide(image,255.0)   
    return tf.train.batch([image],batch_size) 

  這裏的date_file是指文件夾所在的路徑,不包括文件名。第一句是遍歷指定目錄下的文件名稱,存放到一個list中。當然這個做法有很多種方法,比如glob.glob,或者tf.train.match_filename_once

全部代碼如下:

import tensorflow as tf
import os
def read_image(data_file,batch_size):
    data_names=[os.path.join(data_file,k) for k in os.listdir(data_file)]
    filenames_queue=tf.train.string_input_producer(data_names,num_epochs=5,shuffle=True,capacity=30)
    reader=tf.WholeFileReader()
    _,img_bytes=reader.read(filenames_queue)
    image=tf.image.decode_jpeg(img_bytes,channels=1)
    image=tf.image.resize_images(image,(180,180))

    image=tf.image.convert_image_dtype(image,tf.float32)
    return tf.train.batch([image],batch_size)

def main( ):
    img_path=r'F:\dataSet\WIDER\WIDER_train\images\6--Funeral'  #本地的一個數據集目錄,有足夠的圖像
    img=read_image(img_path,batch_size=10)
    image=img[0]  #取出每個batch的第一個數據
    print(image)
    init=[tf.global_variables_initializer(),tf.local_variables_initializer()]
    with tf.Session() as sess:
        sess.run(init)
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess,coord=coord)
        try:
            while not coord.should_stop():
                print(image.shape)
        except tf.errors.OutOfRangeError:
            print('read done')
        finally:
            coord.request_stop()
        coord.join(threads)


if __name__=="__main__":
    main()

"""
輸出如下:
(180, 180, 1)
(180, 180, 1)
(180, 180, 1)
(180, 180, 1)
(180, 180, 1)
"""

  這段代碼可以說寫的很是規整了。注意到init裏面有對local變量的初始化,並且因為用到了隊列,當然要告訴電腦什麼時候隊列開始, tf.train.Coordinator 和 tf.train.start_queue_runners 就是兩個管理隊列的類,用法如程序所示。

  與 tf.train.string_input_producer相似的函數是 tf.train.slice_input_producer。 tf.train.slice_input_producer和tf.train.string_input_producer的第一個參數形式不一樣。等有時間再做一個二者比較的博客

 3、對TFRecorder解碼獲得圖像數據

  其實這塊和上一種方式差不多的,更重要的是怎麼生成TFRecorder文件,這一部分我會補充到另一篇博客上。

  仍然使用 tf.train.string_input_producer。

import tensorflow as tf
import matplotlib.pyplot as plt
import os
import cv2
import  numpy as np
import glob

def read_image(data_file,batch_size):
    files_path=glob.glob(data_file)
    queue=tf.train.string_input_producer(files_path,num_epochs=None)
    reader = tf.TFRecordReader()
    print(queue)
    _, serialized_example = reader.read(queue)
    features = tf.parse_single_example(
        serialized_example,
        features={
            'image_raw': tf.FixedLenFeature([], tf.string),
            'label_raw': tf.FixedLenFeature([], tf.string),
        })
    image = tf.decode_raw(features['image_raw'], tf.uint8)
    image = tf.cast(image, tf.float32)
    image.set_shape((12*12*3))
    label = tf.decode_raw(features['label_raw'], tf.float32)
    label.set_shape((2))
    # 預處理部分省略,大家可以自己根據需要添加
    return tf.train.batch([image,label],batch_size=batch_size,num_threads=4,capacity=5*batch_size)

def main( ):
    img_path=r'F:\python\MTCNN_by_myself\prepare_data\pnet*.tfrecords'  #本地的幾個tf文件
    img,label=read_image(img_path,batch_size=10)
    image=img[0]
    init=[tf.global_variables_initializer(),tf.local_variables_initializer()]
    with tf.Session() as sess:
        sess.run(init)
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess,coord=coord)
        try:
            while not coord.should_stop():
                print(image.shape)
        except tf.errors.OutOfRangeError:
            print('read done')
        finally:
            coord.request_stop()
        coord.join(threads)


if __name__=="__main__":
    main()

  在read_image函數中,先使用glob函數獲得了存放tfrecord文件的列表,然後根據TFRecord文件是如何存的就如何parse,再set_shape;這裡有必要提醒下parse的方式。我們看到這裏用的是tf.decode_raw ,因為做TFRecord是將圖像數據string化了,數據是串行的,丟失了空間結果。從features中取出image和label的數據,這時就要用 tf.decode_raw  解碼,得到的結果當然也是串行的了,所以set_shape 成一個串行的,再reshape。這種方式是取決於你的編碼TFRecord方式的。

再舉一種例子:

reader=tf.TFRecordReader()
_,serialized_example=reader.read(file_name_queue)
features = tf.parse_single_example(serialized_example, features={
    'data': tf.FixedLenFeature([256,256], tf.float32), ###
    'label': tf.FixedLenFeature([], tf.int64),
    'id': tf.FixedLenFeature([], tf.int64)
})
img = features['data']
label =features['label']
id = features['id']

  這個時候就不需要任何解碼了。因為做TFRecord的方式就是直接把圖像數據append進去了。

參考鏈接:

  https://blog.csdn.net/qq_34914551/article/details/86286184

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

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

我從LongAdder中窺探到了高併發的秘籍,上面只寫了兩個字…

這是why的第 53 篇原創文章

荒腔走板

大家好,我是why。

時間過的真是快,一周又要結束了。那麼,你比上周更博學了嗎?先來一個簡短的荒腔走板,給冰冷的技術文注入一絲色彩。

上面這圖是我之前拼的一副拼圖,一共劃分了800塊,背面無提示,難度極高,我花了兩周的時間才拼完。

拼的是壇城,傳說中佛祖居住生活的地方。

第一次知道這個名詞是 2015 年,窩在寢室看紀錄片《第三極》。

其中有一個片段講的就是僧人為了某個節日用沙繪畫壇城,他們的那種專註,虔誠,真摯深深的打動了我,當宏偉的壇城畫完之後,他靜靜的等待節日的到來。

本以為節日當天眾人會對壇城頂禮膜拜,而實際情況是大家手握一炷香,看着眾僧人快速的摧毀壇城。

還沒來得及仔細欣賞那複雜的美麗的圖案,卻又用掃把掃的乾乾凈凈。

掃把掃下去的那一瞬間,我的心受到了一種強烈的撞擊:可以辛苦地拿起,也可以輕鬆地放下。

看到摧毀壇城的片段的時候,有一個彈幕是這樣說的:

一切有為法,如夢幻泡影,如露亦如電,應作如是觀。

這句話出自《金剛般若波羅蜜經》第三十二品,應化非真分。

因為之前翻閱過幾次《金剛經》,看到這句話的時候我一下就想起了它。

因為讀的時候我就覺得這句話很有哲理,但是也似懂非懂。所以印象比較深刻。

當他再次在壇城這個畫面上以彈幕的形式展現在我的眼前的時候,我一下就懂了其中的哲理,不敢說大徹大悟,至少領悟一二。

觀看摧毀壇城,這個色彩斑斕的世界變幻消失的過程,正常人的感受都是震撼,轉而覺得可惜,心裏久久不能平靜。

但是僧人卻風輕雲淡的說:一切有為法,如夢幻泡影,如露亦如電,應作如是觀。

好了,說迴文章。

先說AtomicLong

關於 AtomicLong 我就不進行詳細的介紹了。

先寫這一小節的目的是預熱一下,拋出一個問題,而這個問題是關於 CAS 操作和 volatile 關鍵字的。

我不知道源碼為什麼這樣寫,希望知道答案的朋友指點一二。

抱拳了,老鐵。

為了順利的拋出這個問題,我就得先用《Java併發編程的藝術》一書做引子,引出這個問題。

首先在書的第 2.3 章節《原子操作的實現原理》中介紹處理器是如何實現原子操作時提到了兩點:

  • 使用總線鎖保證原子性。

  • 使用緩存鎖保證原子性。

所謂總線鎖就是使用處理器提供一個提供的一個 LOCK # 信號,當一個處理器在總線上輸出此信號時,其他處理器的請求將被阻塞住,那麼該處理器可以獨佔共享內存。

總線鎖保證原子性的操作有點簡單粗暴直接了,導致總線鎖定的開銷比較大。

所以,目前處理器在某些場合下使用緩存鎖來進行優化。

緩存鎖的概念可以看一下書裏面怎麼寫的:

其中提到的圖 2-3 是這樣的:

其實關鍵 Lock 前綴指令。

被 Lock 前綴指令操作的內存區域就會加鎖,導致其他處理器不能同時訪問。

而根據 IA-32 架構軟件開發者手冊可以知道,Lock 前綴的指令在多核處理器下會引發兩件事情:

  • 將當前處理器緩存行的數據寫回系統內存。
  • 這個寫回內存的操作會使在其他 CPU 里緩存了該內存地址的數據無效。

對於 volatile 關鍵字,毫無疑問,我們是知道它是使用了 Lock 前綴指令的。

那麼問題來了,JVM 的 CAS 操作使用了 Lock 前綴指令嗎?

是的,使用了。

JVM 中的 CAS 操作使用的是處理器通過的 CMPXCHG 指令實現的。這也是一個 Lock 前綴指令。

好,接下來我們看一個方法:

java.util.concurrent.locks.AbstractQueuedLongSynchronizer#compareAndSetState

這個方法位於 AQS 包裏面,就是一個 CAS 的操作。現在只需要關心我框起來的部分。

英文部分翻譯過來是:這個操作具有 volatile 讀和寫的內存語言。

而這個操作是什麼操作?

就是 344 行 unsafe 的 compareAndSwapLong 操作,這個方法是一個 native 方法。

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

為什麼這個操作具有 volatile 讀和寫的內存語言呢?

書裏面是這樣寫的:

這個本地方法的最終實現在 openjdk 的如下位置:
openjdk-7-fcs-src-b147- 27_jun_2011\openjdk\hotspot\src\os_cpu\windows_x86\vm\atomic_windows_x86.inline.hpp(對應於Windows操作系統,X86處理器)

intel 的手冊對 Lock 前綴的說明如下。

  • 確保對內存的讀-改-寫操作原子執行。在 Pentium 及 Pentium 之前的處理器中,帶有 Lock 前綴的指令在執行期間會鎖住總線,使得其他處理器暫時無法通過總線訪問內存。很顯然,這會帶來昂貴的開銷。從Pentium 4、Intel Xeon及P6處理器開始,Intel使用緩存鎖定(Cache Locking) 來保證指令執行的原子性。緩存鎖定將大大降低lock前綴指令的執行開銷。

  • 禁止該指令,與之前和之後的讀和寫指令重排序。

  • 把寫緩衝區中的所有數據刷新到內存中。

上面的第2點和第3點所具有的內存屏障效果,足以同時實現 volatile 讀和volatile 寫的內存語義。

好,如果你說你對書上的內容存疑。那麼我帶大家再看看官方文檔:

https://docs.oracle.com/javase/8/docs/api/

我框起來的部分:

compareAndSet 和所有其他的諸如 getAndIncrement 這種讀然後更新的操作擁有和 volatile 讀、寫一樣的內存語義。

原因就是用的到了 Lock 指令。

好,到這裏我們可以得出結論了:

compareAndSet 同時具有volatile讀和volatile寫的內存語義。

那麼問題就來了!

這個操作,在 AtomicLong 裏面也有調用:

而 AtomicLong 裏面的 value 又是被 volatile 修飾了的:

請問:為什麼 compareAndSwapLong 操作已經同時具有 volatile 讀和 volatile 寫的內存語義了,其操作的 value 還需要被 volatile 修飾呢?

這個問題也是一個朋友拋出來探討的,探討的結果是,我們都不知道為什麼:

我猜測會不會是由於操作系統不同而不同。在 x86 上面運行是這樣,其他的操作系統就不一定了,但是沒有證據。

希望知道為什麼這樣做的朋友能指點一下。

好,那麼前面說到 CAS ,那麼一個經典的面試題就來了:

請問,CAS 實現原子操作有哪些問題呢?

  • ABA問題。

  • 循環時間開銷大。

  • 只能保證一個共享變量的原子操作。

如果上面這三點你不知道,或者你說不明白,那我建議你看完本文後一定去了解一下,屬於面試常問系列。

我主要說說這個循環時間開銷大的問題。自旋 CAS 如果長時間不成功,就會對 CPU 帶來比較大的執行開銷。

而回答這個問題的朋友,大多數舉例的時候都會說: “AtomicLong 就是基於自旋 CAS 做的,會帶來一定的性能問題。巴拉巴拉……”

而我作為面試官的時候只是微笑着看着你,讓你錯以為自己答的很完美。

我知道你為什麼這樣答,因為你看了幾篇博客,刷了刷常見面試題,那裡面都是這樣寫的 :AtomicLong 就是基於自旋 CAS 做的。

但是,朋友,你可以這樣說,但是回答不完美。這題得分別從 JDK 7 和 JDK 8 去答:

JDK 7 的 AtomicLong 是基於自旋 CAS 做的,比如下面這個方法:

while(true) 就是自旋,自旋裏面純粹依賴於 compareAndSet 方法:

這個方法裏面調用的 native 的 comareAndSwapLong 方法,對應的 Lock 前綴指令就是我們前面說到的 cmpxchg。

而在 JDK 8 裏面 AtomicLong 裏面的一些方法也是自旋,但是就不僅僅依賴於 cmpxchg 指令做了,比如還是上面這個方法:

可以看到這裏面還是有一個 do-while 的循環,還是調用的 compareAndSwapLong 方法:

這個方法對應的 Lock 前綴指令是我們前面提到過的 xadd 指令。

從 Java 代碼的角度來看,都是自旋,都是 compareAndSwapLong 方法。沒有什麼差異。

但是從這篇 oracle 官網的文章,我們可以窺見 JDK 8 在 x86 平台上對 compareAndSwapLong 方法做了一些操作,使用了 xadd 彙編指令代替 CAS 操作。

xadd 指令是 fetch and add。

cmpxchg 指令是 compare and swap。

xadd 指令的性能是優於 cmpxchg 指令的。

具體可以看看這篇 oracle 官網的文章:

https://blogs.oracle.com/dave/atomic-fetch-and-add-vs-compare-and-swap

文章下面的評論,可以多注意一下,我截取其中兩個,大家品一品:

然後是這個:

總之就是:這篇文章說的有道理,我們(Dave and Doug)也在思考這個問題。所以我們會在 JIT 上面搞事情,在 x86 平台上把 CAS 操作替換為 LOCK:XADD 指令。

(這個地方我之前理解的有問題,經過朋友的指正後才修改過來。)

所以,JDK 8 之後的 AtomicLong 裏面的方法都是經過改良后, xadd+cmpxchg 雙重加持的方法。

另外需要注意的是,我怕有的朋友懵逼,專門多提一嘴:CAS 是指一次比較並交換的過程,成功了就返回 true,失敗了則返回 false,強調的是一次。而自旋 CAS 是在死循環裏面進行比較並交換,只要不返回 true 就一直循環。

所以,不要一提到 CAS 就說循環時間開銷大。前面記得加上“自旋”和“競爭大”兩個條件。

至於 JDK 8 使用 xadd 彙編指令代替 CAS 操作的是否真的是性能更好了,可以看看這篇 oracle 官網的文章:

https://blogs.oracle.com/dave/atomic-fetch-and-add-vs-compare-and-swap

文章下面的評論,可以多注意一下,我截取其中一個,大家品一品:

經過我們前面的分析,AtomicLong 從 JDK 7 到 JDK 8 是有一定程度上的性能優化的,但是改動並不大。

還是存在一個問題:雖然它可以實現原子性的增減操作,但是當競爭非常大的時候,被操作的這個 value 就是一個熱點數據,所有線程都要去對其進行爭搶,導致併發修改時衝突很大。

所以,歸根到底它的主要問題還是出在共享熱點數據上。

為了解決這個問題,Doug Lea 在 JDK 8 裏面引入了 LongAdder 類。

更加牛逼的LongAdder

大家先看一下官網上的介紹:

上面的截圖一共兩段話,是對 LongAdder 的簡介,我給大家翻譯並解讀一下。

首先第一段:當有多線程競爭的情況下,有個叫做變量集合(set of variables)的東西會動態的增加,以減少競爭。sum() 方法返回的是某個時刻的這些變量的總和。

所以,我們知道了它的返回值,不論是 sum() 方法還是 longValue() 方法,都是那個時刻的,不是一個準確的值。

意思就是你拿到這個值的那一刻,這個值其實已經變了。

這點是非常重要的,為什麼會是這樣呢?

我們對比一下 AtomicLong 和 LongAdder 的自增方法就可以知道了:

AtomicLong 的自增是有返回值的,就是一個這次調用之後的準確的值,這是一個原子性的操作。

LongAdder 的自增是沒有返回值的,你要獲取當前值的時候,只能調用 sum 方法。

你想這個操作:先自增,再獲取值,這就不是原子操作了。

所以,當多線程併發調用的時候,sum 方法返回的值必定不是一個準確的值。除非你加鎖。

該方法上的說明也是這樣的:

至於為什麼不能返回一個準確的值,這就是和它的設計相關了,這點放在後面去說。

然後第二段:當在多線程的情況下對一個共享數據進行更新(寫)操作,比如實現一些統計信息類的需求,LongAdder 的表現比它的老大哥 AtomicLong 表現的更好。在併發不高的時候,兩個類都差不多。但是高併發時 LongAdder 的吞吐量明顯高一點,它也佔用更多的空間。這是一種空間換時間的思想。

這段話其實是接着第一段話在進行描述的。

因為它在多線程併發情況下,沒有一個準確的返回值,所以當你需要根據返回值去搞事情的時候,你就要仔細思考思考,這個返回值你是要精準的,還是大概的統計類的數據就行。

比如說,如果你是用來做序號生成器,所以你需要一個準確的返回值,那麼還是用 AtomicLong 更加合適

如果你是用來做計數器,這種寫多讀少的場景。比如接口訪問次數的統計類需求,不需要時時刻刻的返回一個準確的值,那就上 LongAdder 吧

總之,AtomicLong 是可以保證每次都有準確值,而 LongAdder 是可以保證最終數據是準確的。高併發的場景下 LongAdder 的寫性能比 AtomicLong 高。

接下來探討三個問題:

  • LongAdder 是怎麼解決多線程操作熱點 value 導致併發修改衝突很大這個問題的?

  • 為什麼高併發場景下 LongAdder 的 sum 方法不能返回一個準確的值?

  • 為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

先帶大家看個圖片,看不懂沒有關係,先有個大概的印象:

接下來我們就去探索源碼,源碼之下無秘密。

從源碼我們可以看到 add 方法是關鍵:

裏面有 cells 、base 這樣的變量,所以在解釋 add 方法之前,我們先看一下 這幾個成員變量。

這幾個變量是 Striped64 裏面的。

LongAdder 是 Striped64 的子類:

其中的四個變量如下:

  • NCPU:cpu 的個數,用來決定 cells 數組的大小。

  • cells:一個數組,當不為 null 的時候大小是 2 的次冪。裏面放的是 cell 對象。

  • base : 基數值,當沒有競爭的時候直接把值累加到 base 裏面。還有一個作用就是在 cells 初始化時,由於 cells 只能初始化一次,所以其他競爭初始化操作失敗線程會把值累加到 base 裏面。

  • cellsBusy:當 cells 在擴容或者初始化的時候的鎖標識。

之前,文檔裏面說的 set of variables 就是這裏的 cells。

好了,我們再回到 add 方法裏面:

cells 沒有被初始化過,說明是第一次調用或者競爭不大,導致 CAS 操作每次都是成功的。

casBase 方法就是進行 CAS 操作。

當由於競爭激烈導致 casBase 方法返回了 false 后,進入 if 分支判斷。

這個 if 分子判斷有 4 個條件,做了 3 種情況的判斷

  • 標號為 ① 的地方是再次判斷 cells 數組是否為 null 或者 size 為 0 。as 就是 cells 數組。

  • 標號為 ② 的地方是判斷當前線程對 cells 數組大小取模后的值,在 cells 數組裡面是否能取到 cell 對象。

  • 標號為 ③ 的地方是對取到的 cell 對象進行 CAS 操作是否能成功。

這三個操作的含義為:當 cells 數組裡面有東西,並且通過 getProbe() & m算出來的值,在 cells 數組裡面能取到東西(cell)時,就再次對取到的 cell 對象進行 CAS 操作。

如果不滿足上面的條件,則進入 longAccumulate 函數。

這個方法主要是對 cells 數組進行操作,你想一個數組它可以有三個狀態:未初始化、初始化中、已初始化,所以下面就是對這三種狀態的分別處理:

  • 標號為 ① 的地方是 cells 已經初始化過了,那麼這個裡面可以進行在 cell 裏面累加的操作,或者擴容的操作。

  • 標號為 ② 的地方是 cells 沒有初始化,也還沒有被加鎖,那就對 cellsBusy 標識進行 CAS 操作,嘗試加鎖。加鎖成功了就可以在這裏面進行一些初始化的事情。

  • 標號為 ③ 的地方是 cells 正在進行初始化,這個時候就在 base 基數上進行 CAS 的累加操作。

上面三步是在一個死循環裏面的。

所以如果 cells 還沒有進行初始化,由於有鎖的標誌位,所以就算併發非常大的時候一定只有一個線程去做初始化 cells 的操作,然後對 cells 進行初始化或者擴容的時候,其他線程的值就在 base 上進行累加操作。

上面就是 sum 方法的工作過程。

感受到了嗎,其實這就是一個分段操作的思想,不知道你有沒有想到 ConcurrentHashMap,也不奇怪,畢竟這兩個東西都是 Doug Lea 寫的。

然後再補充說明一下,cells 的初始化大小為 2:

cells 的最大值為 CPU 核數:

cell 是被 Contended 註解修飾了,為了解決偽共享的問題:

說起偽共享,我想起了之前的《一個困擾我122天的技術問題,我好像知道答案了》這篇文章中提到的一個猜想:

後來,我也用這個註解去解決偽共享的問題了,可惜最終的實驗結果表明不是這個原因。

那篇文章發布後有很多朋友給我反饋他們的看法,而更多的是在這條路上發現了更多更多的玄學問題,但是最終這些問題的背後都指向了同一個東西:JIT。

扯遠了,說回本文的這個 LongAdder。

總的來說,就是當沒有衝突的時候 LongAdder 表現的和 AtomicLong 一樣。當有衝突的時候,才是 LongAdder 表現的時候,然後我們再回去看這個圖,就能明白怎麼回事了:

好了,現在我們回到前面提出的三個問題:

  • LongAdder 是怎麼解決多線程操作熱點 value 導致併發修改衝突很大這個問題的?

  • 為什麼高併發場景下 LongAdder 的 sum 方法不能返回一個準確的值?

  • 為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

它們其實是一個問題。

因為 LongAdder 把熱點 value 拆分了,放到了各個 cell 裏面去操作。這樣就相當於把衝突分散到了 cell 裏面。所以解決了併發修改衝突很大這個問題。

當發生衝突時 sum= base+cells。高併發的情況下當你獲取 sum 的時候,cells 極有可能正在被其他的線程改變。一個在高併發場景下實時變化的值,你要它怎麼給你個準確值?當然,你也可以通過加鎖操作拿到當前的一個準確值,但是這種場景你還用啥 LongAdder,是 AtomicLong 不香了嗎?

為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

你發動你的小腦殼想一想,朋友。

AtomicLong 不管有沒有衝突,它寫的都是一個共享的 value,有衝突的時候它就在自旋。

LongAdder 沒有衝突的時候表現的和 AtomicLong 一樣,有衝突的時候就把衝突分散到各個 cell 裏面了,衝突分散了,寫的當然更快了。

一點思考

本文的題目是《我從LongAdder中窺探到了高併發的秘籍,上面就寫了兩個字……》。

那麼這兩個字是什麼呢?

就是拆分。我淺顯的覺得分佈式、高併發都是基於拆分思想的。

本文的 LongAdder 就不說了。

微服務化、分庫分表、讀寫分離……這些東西都是在拆分,把集中的壓力分散開來。

我們常常說性能不行了,那就堆機器解決,這就是在做拆分。

當然,拆分了帶來好處的同時也是有一定的問題的。

比如老大難的分佈式事務、數據聚合查詢等需求。

舉一個我遇到過的例子吧。

在寫這篇文章之前,我看了 LongAdder 源碼,了解到它這樣的結構后,知道了它和 AtomicLong 之間的差異后,我想起了之前做過的一個需求。

就是賬戶服務,有個大商戶的賬戶是一個熱點賬戶,交易非常的頻繁。

這個賬戶上的金額就相當於是一個共享的熱點數據。

我們當時的做法是把這個賬戶拆分為多個影子賬戶,這樣就把熱點賬戶拆分成了多個影子賬戶,壓力就分攤了。

其實這個思想和 LongAdder 是一脈相承的。

這個場景下拆分帶來的問題是什麼呢?

其中一個問題就是這個賬戶的總餘額是多個影子賬戶之和,而每個影子賬戶上的餘額是時刻在變化的,所以我們不能保證餘額是一個實時準確的值。

但是商戶不關心這個呀。他只關心上日餘額是準確的,每日對賬都能對上就行了。

我們在滿足需求的同時,性能還上去了。

還有一個簡單的思考是如果我們把“實現原子操作進行加減”這句話當做一個需求。

我個人拙見是這樣的,AtomicLong 類就是實現了這個需求,交付出去后,它能用,能正常工作,而且還附送了一個功能是每次都給你返回一個準確的值。

而 LongAdder 就是更加優雅的實現了這個需求,它是在原有的基礎上進行了迭代開發,功能還是能一樣的實現,沒有附加功能,但是針對某些場景來說,更好用了。

它們傳遞給我的思想不是我們常說的:先上,能跑就行,後期再迭代。

而是:它確實能跑,但是還有更加快,更加優雅的實現方式,我們可以實現它。

這是我們需要學習的地方。

最後說兩句(求關注)

才疏學淺,難免會有紕漏,如果你發現了錯誤的地方,還請你留言指出來,我對其加以修改。

感謝您的閱讀,我堅持原創,十分歡迎並感謝您的關注。

我是 why,一個被代碼耽誤的文學創作者,不是大佬,但是喜歡分享,是一個又暖又有料的四川好男人。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Model S爆出第三起電池起火事件 Tesla股價大跌

美國知名電動車大廠特斯拉 (Tesla)熱門車款 Model S,週三 (6 日) 傳出近日第三起電池起火事件,引發外界對於爭議性高的電動車輛安全再掀疑慮。Tesla 週三股價才因前日盤後發布第三季車輛銷售不如預期而下挫,週四股價再因上述消息大跌 7.53%,收 139.77 美元。

這起 Tesla 電池起火事件發生在美國田納西州的 Murfreesboro 市,駕駛者 Juris Shibayama 週三下午開著 Model S 駛過路上遺落的拖車掛鉤,因刺破了車輛的電池部位而造成車輛起火。所幸駕駛者在起火之前逃出,並未受傷。

據CNBC報導,這已是過去6 週 Model S 傳出的第 3 起電池起火事件。第 1 次事件發生在西雅圖,當時也是車輛駛過路上一大塊金屬物體,導致電池部分被刺穿而起火。美國國家公路交通安全管理局 (NHTSA)針對上述事件的立場是,他們正在監視情況發展,但並未展開正式調查。

而最新週三的這次車輛起火事件過後,NHTSA 仍表示目前處於搜集資料階段,將諮詢事發當局來確定事故是否與車輛安全相關。

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

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

英國三季度電動汽車銷量環比增25%

據英國媒體報導,第三季度英國電動汽車的銷量環比增長25%,電動汽車補貼登記數量達到1149台,創下2011年1月以來的最高記錄。

2011年1月,英國政府曾宣佈,在隨後的14個月中,只要用戶購買一輛低碳電動汽車,即將獲得高達5000英鎊的補貼。2012年,政府決定把對電動汽車的補貼措施延長到2015年。

不久前,雷諾—日產公司首席執行官卡洛斯•戈恩表示,2016年底之前,將實現不了150萬輛電動汽車的銷售目標,實現目標有可能是在2020年或2021年。他表示,政府對充電站建設的投入不到位,影響了電動汽車的銷售。

日產公司的純電動汽車「聆風」是政府補貼計畫下第一個受益的主要車型,並避開了英國執政聯盟預算縮減的風潮。

聆風由日產公司桑德蘭工廠生產,今年4月在挪威上市以後一炮打響,成為市場上最暢銷的汽車。當然,這部分得益於挪威慷慨的電動汽車減稅政策。

但是聆風也有不少競爭者,如通用雪佛蘭沃藍達在歐洲大陸的版本Vauxhall Ampera、相對便宜的雷諾Zoe和寶馬i3。此外,還有福特福克斯的電動汽車及特斯拉的豪華電動汽車。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!