環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※回頭車貨運收費標準
※推薦評價好的iphone維修中心
※超省錢租車方案
※台中搬家遵守搬運三大原則,讓您的家具不再被破壞!
※推薦台中搬家公司優質服務,可到府估價
摘錄自2020年10月24日中央通訊社報導
中國國家主席習近平9月22日在聯合國大會承諾,中國二氧化碳排放將在2030年前達到峰值,2060年前實現碳中和。
歐洲聯盟外長波瑞爾(Josep Borrell)10月22日在個人部落格發表文章,習近平已提出中國2060年前實現碳中和的承諾,加上歐洲正致力氣候外交,這可能是全球應對氣候變遷的重要轉折。他強調,雖然設定一個雄心勃勃的目標很重要,但更重要的是取得成果,而中國迄今尚未詳細說明要如何實現2060年的目標。中國在一帶一路倡議下,其中逾4成投資與能源建設相關,這導致化石燃料發電廠建設增加,這個議題應納入未來歐中對話的議程。
歐盟近年將應對氣候變遷推動為氣候多邊外交行動,歐中領導人今年9月視訊會議時,即強調中國是重要的全球合作夥伴,鼓勵中國加強氣候承諾、盡快啟動國家排放交易體系、設定氣候中和的目標,當時歐盟也強調,中國必須暫停在國外建設燃煤電廠和資助相關建設。
氣候變遷
循環經濟
國際新聞
中國
碳排放
碳中和
氣候外交
一帶一路
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※回頭車貨運收費標準
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※推薦評價好的iphone維修中心
※教你寫出一流的銷售文案?
※台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!
※台中搬家遵守搬運三大原則,讓您的家具不再被破壞!
閱讀本文大概需要 1.5 分鐘。
數組本身相對來說比較簡單,能想到的可寫的東西不多。但還是有一些知識點值得總結和知曉一 下。有的知識點,知不知道不重要,工作中用的時候搜索一下就可以了,畢竟實現一個功能代碼的寫法有很多種,再牛的人也不可能完全熟悉一門語言的每個細節。當然了,偶然地知道了一些小知識或小技巧也是一種小小的收穫。在你看這篇小文時,或許這種偶然的事情就正在發生。我們先從數組的初始化開始吧。
定義和初始化一個數組有好幾種方式,隨着 C# 版本升級,方式也越來越簡單:
int[] arr = new int[3]; // 定義一個長度為 3 的數組
int[] arr = new int[3] {1, 2, 3}; // 定義一個長度為 3 的數組並初始化
int[] arr = new [] {1, 2, 3}; // 上面的簡寫
int[] arr = {1, 2, 3}; // 上面的進一步簡寫
我們知道當定義一個固定長度的數組沒有初始化時,比如:
int[] arr = new int[3];
雖然沒有初始化,但它是有默認值的,這個數組中包含了 3 個值為 0 的整數。如何使用非默認值創建一個數組呢?可以使用 System.Linq 命名空間下的 Enumerable.Repeat 方法:
// 創建長度為 5 的整形數組,並用 100 來填充
int[] arr = Enumerable.Repeat(100, 5).ToArray();
// 創建長度為 5 的字符串數組,並用“C#”來填充
string[] arr = Enumerable.Repeat("C#", 5).ToArray();
把一個數組的元素複製到另一個數組,可以使用 Array.Copy() 方法,複製時源數組取值和目標數組賦值都是從索引 0 開始的:
var sourceArray = new int[] { 11, 12, 3, 5, 2, 9};
var destinationArray = new int[3];
Array.Copy(sourceArray, destinationArray, 3);
// destinationArray = [11, 12, 3]
克隆一個數組很簡單:
var sourceArray = new int[] { 11, 12, 3 };
var destinationArray = (int[])sourceArray.Clone();
// destinationArray = [11, 12, 3]
比較兩個數組是否一樣,即兩個數組包含的元素及元素的順序是否都一樣,可以使用數組的 SequenceEqual 方法:
int[] arr1 = { 3, 5, 7 };
int[] arr2 = { 3, 5, 7 };
bool result = arr1.SequenceEqual(arr2); // true
以上只是羅列幾個有代表性的比較快捷簡單的數組操作,在 C# 中藉助 Linq 可以實現更複雜的數組操作,這裏先不作總結。
實際的 C#開發中很少會直接用到指針,在需要進行底層操作時可能會用到。在 C# 中使用指針時需要在 unsafe 上下文中操作:
int[] arr = new int[] {1, 6, 3, 3, 9};
// 使用 foreach
foreach (int element in arr)
{
Console.WriteLine(element);
}
// 使用指針
unsafe
{
int length = arr.Length;
fixed (int* p = arr)
{
int* pInt = p;
while (length-- > 0)
{
Console.WriteLine(*pInt);
pInt++; // 將指針移到下一個元素
}
}
}
// 依次輸出:1 6 3 3 9
這裏只是讓大家知道有這麼一回事,指針不是本篇的話題,更多關於指針的操作可以訪問:
https://bit.ly/2MmIsNl
我就見過有人使用 for 循環生成一個從 n 到 m 的有序數組,其實 C# 提供了 Enumerable.Range 方法可以很容易地創建一個有序的整型數組。示例:
// 創建数字從 1 到 100 的數組
int[] sequence = Enumerable.Range(1, 100).ToArray();
// 結合 Linq 還可以實現更複雜的數組創建邏輯
int[] squares = Enumerable.Range(2, 10).Select(x => x * x).ToArray(); // 4, 9, 16...
簡單來說,多維數組每一行長度都是固定的,比如二維數組是一個 m 行 n 列的矩陣:
int[,] arr = {
{1, 2, 3, 4},
{4, 2, 1, 3},
{2, 1, 3, 4},
}
而交錯數組(又叫鋸齒數組)的每一行可以有不同的大小,表示的是數組的數組。比如:
int[][] arr = {
new [] {1, 2, 3, 4},
new [] {1, 2},
new [] {1, 2, 3},
}
它們的定義、初始化、取值、賦值等都有明顯的區別。
先看多維數組:
// 多維數組的定義
int[,] arr = new int[10, 10]; // 二維數組
int[,,] arr = new int[10, 10, 10]; // 三維數組
// 多維數組的初始化 (new int[3, 2] 可以省略)
int[,] arr = new int[3, 2] { {1, 1}, {2, 2}, {3, 3} };
// 多維數組的取值
Console.WriteLine(arr[2, 1]); // 3
// 多維數組的賦值
arr[2, 1] = 10;
再對比交錯數組:
// 交錯數組的定義
int[][] arr = new int[10][]; // 二層:數組的數組
int[][][] arr = new int[10][][]; // 三層:數組的數組的數組
// 交錯數組的初始化 (new int[3][] 可以省略)
int[][] arr = new int[3][] { new [] {1}, new [] {2, 2}, new [] {3, 3, 3} };
// 交錯數組的取值
Console.WriteLine(arr[2][1]); // 3
// 多維數組的賦值
arr[2][1] = 10;
注意:多維數組每行長度必須一致;交錯數組第二個 [] 是不能有数字的。兩者的 Length 屬性意義也是不一樣的,多維數組的 Length 屬性取的是數組所有元素的總數,而交錯數組取的是第一層的數組的個數。例如:
int[,] arr1 = new int[3, 2] { { 1, 1 }, { 2, 2 }, { 3, 3 } };
Console.WriteLine(arr1.Length); // 輸出:6
int[][] arr2 = new int[3][] { new[] { 1 }, new[] { 2, 2 }, new[] { 3, 3, 3 } };
Console.WriteLine(arr2.Length); // 輸出:3
建議:除了某些像矩陣這樣的操作場景可能更適合使用多維數組,大多數場景應盡量選擇使用交錯數組。功能上多維數組可以實現的,交錯數組也都能實現,反過來不一定可以。另外,根據 stackoverflow 網友的回答(下面參考鏈接),在 .NET 中,交錯數組性能上要好於多維數組。
參考:https://bit.ly/2Mqn6P1
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
※網頁設計最專業,超強功能平台可客製化
※別再煩惱如何寫文案,掌握八大原則!
欲觀原文,請君移步
OSD,on-screen display的簡稱,即屏幕菜單式調節方式。一般我們按一下Menu鍵后屏幕彈出的显示器各項調節項目信息的矩形菜單,比如調亮度,色調,飽和度等信息,這個显示這個菜單的功能就是視頻行業的OSD。
硬件平台是基於xilinx xc7z035芯片開發的,關鍵模塊框圖如下圖1所示。
一個時序產生模塊Video Timing Controller(在本次實驗中採用1080P標準時序)
首先PL端將視頻流通過VDMA讀出,輸出接口為AXI4-Stream的數據流
然後視頻流進入OSD IP(OSD輸入輸出也是AXI4-Stream接口)
最後OSD輸出數據流與1080P時序同時送入到AXI4-Stream to Video Out模塊,輸出為HDMI接口
下面小編會詳細介紹OSD IP的例化與使用
如果在使用OSD IP過程中出現如下錯誤,請在xilinx官網上申請OSD的License,這裏不再詳述如何申請License。
首先在Block Design中加入Video On Screen Display,打開後會看到如下圖2。
(1) 勾選AXI-Lite Interface:PS端通過AXI-Lite進行配置該IP
(2) Video Format選擇RGB
(3) Layers選擇2
(4) Layer Configuration:LAYER0選擇外部視頻流,也就是實時視頻,LAYER1選擇Internal,PS端可以控制進行圖文疊加
點擊Screen Layout Options,如圖3所示
(1) Background size(選擇背景大小)里寬度輸入1920,高度輸入1080
(2) Background color輸入背景顏色,這裏選擇黑色,可以通過axi-lite來控制
(3) layer0因為選擇的是外部視頻流,所以比如設置為外部視頻流分辨率,輸錯了,可能無法正常使用,小編已經遇到過了,本文使用1920×1080外部視頻流
(4) layer1因為選擇的是內部圖像控制器,所以無所謂設置什麼,可以通過axi-lite控制,所以選擇默認即可
點擊LAYER 1 Options出現圖4界面:因為是內部圖像控制器,所以可以進行一些配置,比如顏色多少,字符數目,比特像素等等,這裏小編選擇的是默認。
配置完OSD IP后,將其AXI-lite掛在總線上即可,然後保存Block Design即可。
注:點開Address Editor,一定要確定該IP被分配地址空間,如果沒有,點擊一下自動分配(小編遇到的問題就是這個ip地址空間在unmap里,導致後續PS端OSD IP無法初始化)。
下面就是常規操作include bitstream導出SDK,其實就是生成hdf文件,硬件信息。然後就launch SDk。如圖4所示,可以看到hdf文件里都有什麼。
新建一個design_top的空工程,如圖5所示,在design_top_bsp下面可以看到system.mss文件,在紅框中找到OSD IP。
點擊import examples,出現如圖6所示,勾選對話框后選擇OK(不會玩IP先整個example)。
打開XosdSelfTestExample.c即可看到該例子程序是怎麼個處理流程(圖7為main函數,圖8為使用流程)小編稱之為PS端IP使用三步法
第一步先進行lookup該IP
第二步就是初始化該IP
第三步就是使用IP
運行一下,結果如圖9所示,可以看到UART會打印OSD成功信息。
閑話不說,上面經過了OSD example,小編也作為一個PS端初學者來玩一玩。
尷尬的是經常在寫c代碼的時候想着寫begin…end,真是verilog寫習慣了,思想難以改變,原來是花括弧啊{}
在初始化后必須將該模塊進行複位,然後,否則該IP啟動不了。
int OsdInit(int DeviceID)
{
int Status;
/* Initialize the OSD instance */
OsdCfgPtr = XOSD_LookupConfig(DeviceID);
Status = XOSD_CfgInitialize(&Osd, OsdCfgPtr,OsdCfgPtr->BaseAddress);
if (Status != XST_SUCCESS) return 1;
/* Reset the devices */
XOSD_Reset(&Osd);
/* Enable the OSD device and tell it to pick up the register changes */
XOSD_Enable(&Osd);
XOSD_RegUpdateEnable(&Osd);
return 0;
}
這裏需要注意的是把BANKIndex輸入為1,否則會進行字符填寫方式就需要改變,不符合操作習慣XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);
void Graphics_setting(u8 Gcindex,u8 LayerPriority,u32 ColorData[],u32 *TextData)
{
int width = 1920;
int height = 1080;
int LayerAlphaValue = 0xFF;
int LayerGlobalAlphaEnable = 0;
XOSD_SetLayerAlpha(&Osd, Gcindex, LayerGlobalAlphaEnable,LayerAlphaValue);
XOSD_SetLayerPriority(&Osd, Gcindex, LayerPriority);
XOSD_SetLayerDimension(&Osd, Gcindex, 0, 0, width, height);
XOSD_EnableLayer(&Osd, Gcindex);
/* Load color, font and text and set the active banks */
XOSD_LoadColorLUTBank(&Osd, Gcindex, 0, ColorData);
//set BankIndex is 1(fit our keyboard)
XOSD_LoadCharacterSetBank(&Osd, Gcindex, 1, (u32 *)Font);
XOSD_LoadTextBank(&Osd, Gcindex, 0, (u32 *)TextData);
XOSD_SetActiveBank(&Osd, Gcindex, 0, 0, 0, 0);
}
void OsdDrawText(int Gcindex,int x_pos, int y_pos, int color, int string_index, int text_size)
{
u32 Instruction[XOSD_INS_SIZE];
u16 ObjType = XOSD_INS_OPCODE_BOXTXT; /* A text string XOSD_INS_OPCODE_TXT*/
u8 ObjSize = (text_size<<4); /* Text Scale factor (1x, 2x, 4x, 8x) */
u16 XStart = x_pos; /* Horizontal start pixel of the text */
u16 YStart = y_pos; /* Vertical start line of the text */
u16 XEnd = x_pos; /* Horizontal end pixel of the text (not used) */
u16 YEnd = y_pos; /* Vertical end line of the text (must be same as YStart) */
u8 TextIndex = string_index; /* Index of Text String */
u8 ColorIndex = color; /* Color used to draw text */
XOSD_CreateInstruction(&Osd, Instruction, Gcindex,ObjType, ObjSize, XStart, YStart, XEnd, YEnd,TextIndex, ColorIndex);
XOSD_LoadInstructionList(&Osd, Gcindex, 0, Instruction, 1);
return;
}
前面只給出了兩個圖層,工程退不回去了,目前工程實現的是疊加8個圖層(1個視頻,7個內部圖像控制器)。
百度網盤源碼以及參考文檔鏈接如下
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整
※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!
※教你寫出一流的銷售文案?
※超省錢租車方案
※回頭車貨運收費標準
前文傳送門:
「Python 圖像處理 OpenCV (1):入門」
「Python 圖像處理 OpenCV (2):像素處理與 Numpy 操作以及 Matplotlib 显示圖像」
「Python 圖像處理 OpenCV (3):圖像屬性、圖像感興趣 ROI 區域及通道處理」
「Python 圖像處理 OpenCV (4):圖像算數運算以及修改顏色空間」
「Python 圖像處理 OpenCV (5):圖像的幾何變換」
看到這個詞可能大家都很懵,為啥在圖像處理裏面還會有閾值。
圖像的閾值處理用大白話講就是將圖像轉化為二值圖像(黑白圖),目的是用來提取圖像中的目標物體,將背景和噪聲區分開(可以近似的認為除了目標全是噪聲)。
通常會設定一個閾值 T ,通過 T 將圖像的像素劃分為兩類:大於 T 的像素群和小於 T 的像素群。
首先可以先將圖像轉化為灰度圖像,因為在灰度圖像中,每個像素都只有一個灰度值用來表示當前像素的亮度。
接下來二值化處理可以將圖像中的像素劃分為兩類顏色,一種是大於閾值 T 的,另一種是小於閾值 T 的。
比如最常見的二值圖像:
當灰度值小於閾值 T 的時候,可以將其像素設置為 0 ,表示為黑色。
當灰度值大於閾值 T 的時候,可以將其像素設置為 255 ,表示為白色。
在 OpenCV 中,為我們提供了閾值函數 threshold() 來幫助我們實現二值圖像的處理。
函數如下:
retval, dst = threshold(src, thresh, maxval, type, dst=None)
常用的 5 中處理類型如下:
接下來這幾種處理類型有啥不同,我們一個一個來看。
這種二值處理方式最開始需要選定一個閾值 T ,從 0 ~ 255 之間,我這裏選擇出於中間的那個數 127 。
接下來的處理規則就是這樣的:
接下來開始寫代碼,看我們的馬里奧同學(不知道你們還記不記得我們的馬里奧同學):
import cv2 as cv
src = cv.imread("maliao.jpg")
# BGR 圖像轉灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值圖像處理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
# 显示圖像
cv.imshow("src", src)
cv.imshow("result", b)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
這種方式和上面的二值處理非常相似,只是把處理規則給反了一下:
完整代碼如下:
import cv2 as cv
src = cv.imread("maliao.jpg")
# BGR 圖像轉灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值圖像處理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
# 显示圖像
cv.imshow("src", src)
cv.imshow("result", b)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
從圖像上可以看到,顏色和上面的二值圖像正好相反,大部分的位置都變成了白色。
這種方法還是需要先選定一個閾值 T ,圖像中大於該閾值的像素點被設定為該閾值,小於該閾值的保持不變。
完整代碼如下:
import cv2 as cv
src = cv.imread("maliao.jpg")
# BGR 圖像轉灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值圖像處理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
# 显示圖像
cv.imshow("src", src)
cv.imshow("result", b)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
這種方式實際上是把圖片比較亮的像素處理成為閾值,其他部分保持不變。
這種方式還是需要先選定一個閾值 T ,將小於 T 的像素點設置為 0 黑色,其他的保持不變。
完整代碼如下:
import cv2 as cv
src = cv.imread("maliao.jpg")
# BGR 圖像轉灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值圖像處理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
# 显示圖像
cv.imshow("src", src)
cv.imshow("result", b)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
這個方法是亮的部分不改,把比較暗的部分修改為 0 。
這個和前面的反二值圖像很像,同樣是反閾值化為 0 ,將大於等於 T 的像素點變為 0 ,其餘保持不變。
完整代碼如下:
import cv2 as cv
src = cv.imread("maliao.jpg")
# BGR 圖像轉灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值圖像處理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
# 显示圖像
cv.imshow("src", src)
cv.imshow("result", b)
# 等待显示
cv.waitKey(0)
cv.destroyAllWindows()
這個方法是暗的部分不改,把比較亮的部分修改為 0 。
接下來還是給這幾種閾值處理后的圖像來個全家福,讓大家能有一個直觀的感受,代碼我也給出來,如下:
import cv2 as cv
import matplotlib.pyplot as plt
# 讀取圖像
img=cv.imread('maliao.jpg')
lenna_img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 閾值化處理
ret1, thresh1=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
ret2, thresh2=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
ret3, thresh3=cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
ret4, thresh4=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
ret5, thresh5=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
# 显示結果
titles = ['Gray Img','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [gray_img, thresh1, thresh2, thresh3, thresh4, thresh5]
# matplotlib 繪圖
for i in range(6):
plt.subplot(2, 3, i+1), plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
如果有需要獲取源碼的同學可以在公眾號回復「OpenCV」進行獲取。
https://blog.csdn.net/Eastmount/article/details/83548652
http://www.woshicver.com/
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※別再煩惱如何寫文案,掌握八大原則!
※網頁設計最專業,超強功能平台可客製化
※回頭車貨運收費標準
相信大部分開發人員,或多或少都看過或寫過併發編程的代碼。併發關鍵字除了Synchronized,還有另一大分支Atomic。如果大家沒聽過沒用過先看基礎篇,如果聽過用過,請滑至底部看進階篇,深入源碼分析。
看過Synchronized相關文章的小夥伴應該知道其是不安全的,再次用代碼應驗下其不安全性:
public class testInt { static int number = 0; public static void main(String[] args) throws Exception { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 100000; i++) { number = number+1; } } }; Thread t1 = new Thread(runnable); t1.start(); Thread t2 = new Thread(runnable); t2.start(); t1.join(); t2.join(); System.out.println("number:" + number); } }
運行結果:
在上面的例子中,我們定義一個初始值為0的靜態變量number,再新建並運行兩個線程讓其各執行10萬次的自增操作,如果他是線程安全的,應該兩個線程執行后結果為20萬,但是我們發現最終的結果是小於20萬的,即說明他是不安全的。
在之前Synchronized那篇文章中說過,可以在number=number+1這句代碼上下加Synchronized關鍵字實現線程安全。但是其對資源的開銷較大,所以我們今天再看下另外一種實現線程安全的方法Atomic。
Atomic是jdk提供的一系列包的總稱,這個大家族包括原子整數(AtomicInteger,AtomicLong,AtomicBoolean),原子引用(AtomicReference,AtomicStampedReference,AtomicMarkableReference),原子數組(AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray),更新器(AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater)。
AtomicInteger,AtomicBoolean,AtomicLong三者功能類似,咱就以AtomicInteger為主分析原子類。
先看下有哪些API,及其他們具體啥功能:
public class testInt { public static void main(String[] args) { //定義AtomicInteger類型的變量,值為1 AtomicInteger i = new AtomicInteger(1); //incrementAndGet方法先新增1再返回,所以打印2,此時i為2 System.out.println(i.incrementAndGet()); //getAndIncrement方法先返回值再新增1,所以打印2,此時i為3 System.out.println(i.getAndIncrement()); //get方法返回當前i值,所以打印3,此時i為3 System.out.println(i.get()); //參數為正數即新增,getAndAdd方法先返回值再新增666,所以打印3,此時i為669 System.out.println(i.getAndAdd(666)); //參數為負數即減去,getAndAdd方法先返回值再減去1,所以打印669,此時i為668 System.out.println(i.getAndAdd(-1)); //參數為正數即新增,addAndGet方法先新增666再返回值,所以打印1334,此時i為1334 System.out.println(i.addAndGet(666)); //參數為負數即減去,addAndGet方法先減去-1再返回值,所以打印1333,此時i為1333 System.out.println(i.addAndGet(-1)); //getAndUpdate方法IntUnaryOperator參數是一個箭頭函數,後面可以寫任何操作,所以打印1333,此時i為13331 System.out.println(i.getAndUpdate(x -> (x * 10 + 1))); //最終打印i為13331 System.out.println(i.get()); } }
執行結果:
public class testInt { //1.定義初始值為0的AtomicInteger類型變量number static AtomicInteger number = new AtomicInteger(0); public static void main(String[] args) throws Exception { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 100000; i++) { //2.調用incrementAndGet方法,實現加1操作 number.incrementAndGet(); } } }; Thread t1 = new Thread(runnable); t1.start(); Thread t2 = new Thread(runnable); t2.start(); t1.join(); t2.join(); System.out.println("number:" + number.get()); } }
我們可以看到運行結果是正確的20萬,說明AtomicInteger的確保證了線程安全性,即在多線程的過程中,運行結果還是正確的。但是這存在一個ABA問題,下面將原子引用的時候再說,先立個flag。
我們以incrementAndGet方法為例,看下底層是如何實現的,AtomicInteger類中的incrementAndGet方法調用了Unsafe類的getAndAddInt方法。
public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; }
我們看下getAndAddInt方法,裏面有個循環,直接值為compareAndSwapInt返回值為true,才結束循環。這裏就不得不提CAS,這就是多線程安全性問題的解決方法。
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
線程1和線程2同事獲取了主內存變量值0,線程1加1並寫入主內存,現在主內存變量值1,線程2也加2並嘗試寫入主內存,這個時候是不能寫入主內存的,因為會覆蓋掉線程1的操作,具體過程如下圖。
CAS是在線程2嘗試寫入內存的時候,通過比較並設置(CompareAndSet)發現現在主內存當前值為1,和他剛開始讀取的值0不一樣,所以他會放棄本次修改,重新讀取主內存的最新值,然後再重試下線程2的具體邏輯操作,再次嘗試寫入主內存。如果這時候線程1,再次對主內存進行了修改,線程2發現現在主內存的值又和預期不一樣,所以將放棄本次修改,再次讀取主內存最新值,再次重試並嘗試寫入主內存。我們可以發現這是一個重複比較的過程,即直到和預期初始值一樣,才會寫入主內存,否則將一直讀取重試的循環。這就是上面for循環的意義。
CAS的實現實際上利用了CPU指令來實現的,如果操作系統不支持CAS,還是會加鎖的,如果操作系統支持CAS,則使用原子性的CPU指令。
在日常使用中,我們不止對上述基本類型進行原子操作,而是需要對一些複雜類型進行原子操作,所以需要AtomicReference。
先看不安全的BigDecimal類型:
public class testReference { static BigDecimal number = BigDecimal.ZERO; public static void main(String[] args) throws Exception { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { number=number.add(BigDecimal.ONE); } } }; Thread t1 = new Thread(runnable); t1.start(); Thread t2 = new Thread(runnable); t2.start(); t1.join(); t2.join(); System.out.println(number); } }
運行結果如下圖,我們可以看到兩個線程,自循環1000次加1操作,最終結果應該是2000,可是結果小於2000。
public class testReference { //定義AtomicReference類型BigDecimal變量 static AtomicReference<BigDecimal> number = new AtomicReference<BigDecimal>(BigDecimal.ZERO); public static void main(String[] args) throws Exception { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { //手動寫循環+CAS判斷 while(true){ BigDecimal pre=number.get(); BigDecimal next=number.get().add(BigDecimal.ONE); if(number.compareAndSet(pre,next)) { break; } } } } }; Thread t1 = new Thread(runnable); t1.start(); Thread t2 = new Thread(runnable); t2.start(); t1.join(); t2.join(); System.out.println(number.get()); } }
運行結果如下:
在上面CAS過程中,是通過值比較來知曉是不是能夠更新成功,那如果線程1先加1再減1,這樣主內存還是原來的值,即線程2還是可以更新成功的。但是這樣邏輯錯了,線程1已經發生了修改,線程2不能直接更新成功。
代碼:
public class testInt { static AtomicInteger number = new AtomicInteger(0); public static void main(String[] args) throws Exception { Thread t1 = new Thread(new Runnable() { @Override public void run() { int a = number.get(); System.out.println("開始number:" + a); try { Thread.sleep(5000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(number.compareAndSet(a, a++)); } }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("開始增加操作"); int a = number.incrementAndGet(); System.out.println("當前number:" + a); int b = number.decrementAndGet(); System.out.println("當前number:" + b); } }); t2.start(); t1.join(); t2.join(); } }
我們看線程2對其進行了一系列操作,但是最後打印了還是true,表示可以更新成功的。這顯然不對。
那我們可以使用AtomicStampedReference,為其添加一個版本號。線程1在剛開始讀取主內存的時候,獲取到值為0,版本為1,線程2也獲取到這兩個值,線程1進行加1,減1的操作的時候,版本各加1,現在主內存的值為0,版本為2,而線程2還拿着預計值為0,版本為1的數據嘗試寫入主內存,這個時候因版本不同而更新失敗。具體我們用代碼試下:
public class testInt { static AtomicStampedReference<Integer> number = new AtomicStampedReference<Integer>(0, 0); public static void main(String[] args) throws Exception { Thread t1 = new Thread(new Runnable() { @Override public void run() { int a = number.getReference(); int s = number.getStamp(); System.out.println("開始number:" + a + ",stamp:" + s); try { Thread.sleep(5000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(number.compareAndSet(a, a + 1, s, s + 1)); } }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("開始增加操作"); int a = number.getReference(); int s = number.getStamp(); number.compareAndSet(a, a + 1, s, s + 1); System.out.println("當前number:" + a + ",stamp:" + (s + 1)); a = number.getReference(); s = number.getStamp(); number.compareAndSet(a, a - 1, s, s + 1); System.out.println("當前number:" + a + ",stamp:" + (s+1)); } }); t2.start(); t1.join(); t2.join(); } }
我們可以看到每次操作都會更新stamp(版本號),在最後對比的時候不僅比較值,還比較版本號,所以是不能更新成功的,false.
AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray三者類似,所以以AtomicIntegerArray為例,我們可以將下面AtomicIntegerArray看做是AtomicInteger類型的數組,其底層很類似,就不詳細寫了。
AtomicIntegerArray array = new AtomicIntegerArray(10); array.getAndIncrement(0); // 將第0個元素原子地增加1 AtomicInteger[] array = new AtomicInteger[10]; array[0].getAndIncrement(); // 將第0個元素原子地增加1
字段更新器和原子累加器比較簡單,這裏就不說了。
LongAdder是jdk1.8之後新加的,那為什麼要加他?這個問題,下面將回答,我們先看下如何使用。
public class testLongAdder { public static void main(String[] args) throws Exception { LongAdder number = new LongAdder(); Runnable runnable = new Runnable() { @Override public void run() { for (int j = 0; j < 10000; j++) { number.add(1L); } } }; Thread t1 = new Thread(runnable); Thread t2 = new Thread(runnable); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("number:" + number); } }
我們可以看到LongAdder的使用和AtomicLong大致相同,使用兩個線程Thread1,Thread2對number值各進行一萬次的自增操作,最後的number是正確的兩萬。
那問題來了,既然AtomicLong能夠完成對多線程下的number進行線程安全的操作,那為什麼還要LongAdder?我們先來段代碼比較下,兩個在結果都是正確的前提下,性能方面的差距。
public class testLongAdder { public static void main(String[] args) { //1個線程,進行100萬次自增操作 test1(1,1000000); //10個線程,進行100萬次自增操作 test1(10,1000000); //100個線程,進行100萬次自增操作 test1(100,1000000); } static void test1(int threadCount,int times){ long startTime=System.currentTimeMillis(); AtomicLong number1=new AtomicLong(); List<Thread> threads1=new ArrayList<>(); for(int i=0;i<threadCount;i++) { threads1.add(new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < times; j++) { number1.incrementAndGet(); } } })); } threads1.forEach(thread -> thread.start()); threads1.forEach(thread ->{ try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } ); long endTime=System.currentTimeMillis(); System.out.println("AtomicLong:"+number1+",time:"+(endTime-startTime)); LongAdder number2=new LongAdder(); List<Thread> threads2=new ArrayList<>(); for(int i=0;i<threadCount;i++) { threads2.add(new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < times; j++) { number2.add(1); } } })); } threads2.forEach(thread -> thread.start()); threads2.forEach(thread ->{ try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } ); System.out.println("LongAdder:"+number2+",time:"+(System.currentTimeMillis()-endTime)); } }
上述代碼對比了1個線程,10個線程,100個線程在進行100百次自增操作后,AtomicLong和LongAdder所花費的時間。通過打印語句,我們發現在最終number1和number2都正確的基礎上,LongAdder花費的時間比AtomicLong少了一個量級。
那為什麼會導致這種情況,我們就要從源碼層面分析。AtomicLong為什麼效率低?因為如果線程數量一多,尤其在高併發的情況下,比如有100個線程同時想要對對象進行操作,肯定只有一個線程會獲取到鎖,其他99個線程可能空轉,一直循環知道線程釋放鎖。如果該線程操作完畢釋放了鎖,其他99個線程再次競爭,也只有一個線程獲取鎖,另外98個線程還是空轉,直到鎖被釋放。這樣CAS操作會浪費大量資源在空轉上,從而使得AtomicLong在線程數越來越多的情況下越來越慢。
AtomicLong是多個線程對同一個value值進行操作,導致多個線程自旋次數太多,性能降低。而LongAdder在無競爭的情況,跟AtomicLong一樣,對同一個base進行操作,當出現競爭關係時則是採用化整為零的做法,從空間換時間,用一個數組cells,將一個value拆分進這個數組cells。多個線程需要同時對value進行操作時候,可以對線程id進行hash得到hash值,再根據hash值映射到這個數組cells的某個下標,再對該下標所對應的值進行自增操作。當所有線程操作完畢,將數組cells的所有值和無競爭值base都加起來作為最終結果。
我們先看下LongAdder裏面的字段,發現其裏面沒有,主要是在其繼承的Stripped64類中,有下面四個主要變量。
/** CPU數量,即cells數組的最大長度*/ static final int NCPU = Runtime.getRuntime().availableProcessors(); /** *cells數組,為2的冪,2,4,8,16.....,方便以後位運算 */ transient volatile Cell[] cells; /** * 基值,主要用於沒有競爭的情況,通過CAS更新。 */ transient volatile long base; /** * 調整單元格大小(擴容),創建單元格時使用的鎖。 */ transient volatile int cellsBusy;
下面是add方法開始。
public void add(long x) { //as:cells數組的引用 //b:base的基礎值 //v:期望值 //m:cells數組大小 //a:當前數組命中的單元 Cell[] as; long b, v; int m; Cell a; //as不為空(cells已經初始化過,說明之前有其他線程對初始化)或者CAS操作不成功(線程間出現競爭) if ((as = cells) != null || !casBase(b = base, b + x)) { //初始化uncontented,true表示未競爭(因為有兩個情況,這裏先初始化,後面對其修改,就能區分這兩種情況) boolean uncontended = true; //as等於null(cells未初始化) //或者線程id哈希出來的下標所對應的值為空(cell等於空),getProbe() & m功能是獲取下標,底層邏輯是位運算 //或者更新失敗為false,即發生競爭,取非就為ture if (as == null || (m = as.length - 1) < 0 || (a = as[getProbe() & m]) == null || !(uncontended = a.cas(v = a.value, v + x))) //進入到if裏面,說明更新case失敗,或者更新某個cell也失敗了,或者cell為空,或者cells為空 longAccumulate(x, null, uncontended); } }
從LongAdder調用Stripped64的longAccumulate方法,主要是初始化cells,cells的擴容,多個線程同時命中一個cell的競爭操作。
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) { //x:add的值,fn:為null,wasUncontended:是否發生競爭,true為發生競爭,false為不發生競爭 int h;//線程的hash值 //如果該線程為0,即第一次進來,所以ThreadLocalRandom強制初始化線程id,再對其hash if ((h = getProbe()) == 0) { ThreadLocalRandom.current(); h = getProbe(); wasUncontended = true; } //擴容意向,為false肯定不擴容,為true可能擴容 boolean collide = false; //死循環 for (;;) { //as:cells數組的引用 //a:當前線程命中的cell //n:cells的長度 //v:當前線程命中的cell所擁有的value值 Cell[] as; Cell a; int n; long v; //cells不為空 if ((as = cells) != null && (n = as.length) > 0) { //當前線程命中的cell為空,下面邏輯是新增cell if ((a = as[(n - 1) & h]) == null) { if (cellsBusy == 0) { // Try to attach new Cell Cell r = new Cell(x); // Optimistically create if (cellsBusy == 0 && casCellsBusy()) { boolean created = false; try { // Recheck under lock Cell[] rs; int m, j; if ((rs = cells) != null && (m = rs.length) > 0 && rs[j = (m - 1) & h] == null) { rs[j] = r; created = true; } } finally { cellsBusy = 0; } if (created) break; continue; // Slot is now non-empty } } collide = false; } //發生競爭 else if (!wasUncontended) // CAS already known to fail wasUncontended = true; // Continue after rehash //沒有競爭,嘗試修改當前線程對應的cell值,成功跳出循環 else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; //如果n大於CPU最大數量,不可擴容 else if (n >= NCPU || cells != as) collide = false; // At max size or stale else if (!collide) collide = true; //獲取到了鎖,進行擴容,為2的冪, else if (cellsBusy == 0 && casCellsBusy()) { try { if (cells == as) { // Expand table unless stale Cell[] rs = new Cell[n << 1];//左移一位運算符,數量加倍 for (int i = 0; i < n; ++i) rs[i] = as[i]; cells = rs; } } finally { cellsBusy = 0; } collide = false; continue; // Retry with expanded table } h = advanceProbe(h); } //cells等於空,並且獲取到鎖,開始初始化工作,創建結束釋放鎖,繼續循環 else if (cellsBusy == 0 && cells == as && casCellsBusy()) { boolean init = false; try { // Initialize table if (cells == as) { Cell[] rs = new Cell[2]; rs[h & 1] = new Cell(x); cells = rs; init = true; } } finally { cellsBusy = 0; } if (init) break; } else if (casBase(v = base, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; // Fall back on using base } }
結束了,撒花。這篇主要說了Atomic的一些使用,包括Atomic原子類(AtomicInteger,AtomicLong,AtomicBoolean),Atomic原子引用(AtomicReference,AtomicStampedReference),以及1.8之後LongAdder的優勢,源碼分析。過程還穿插了一些CAS,ABA問題引入和解決方式。
Java多線程進階(十七)—— J.U.C之atomic框架:LongAdder
CAS原理
Java 8 Performance Improvements: LongAdder vs AtomicLong
AtomicInteger深入理解
原子操作類AtomicInteger詳解
玩轉Java併發工具,精通JUC,成為併發多面手
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※想知道最厲害的網頁設計公司"嚨底家"!
※別再煩惱如何寫文案,掌握八大原則!
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※回頭車貨運收費標準
※台中搬家公司費用怎麼算?
6T渦輪增壓發動機,最大功率132。4千瓦,最大扭矩265牛米,傳動系統方面只有1。6T車型是搭載7擋雙離合變速箱,2。0L和2。4L都是配備傳統的6擋手自一體,在動力的輸出上,1。6T車型前段的加速比2。0L、2。4L車型來得會更加直接,而在中後段就有種動力衰弱的感覺,在平順性方面,2。
現在年輕的消費者,在購車方面更多是注重外觀漂不漂亮,在空間上並不會像前輩們這麼注重,而更多的是強調自己個性潮流的一面,所以買車首選就是外觀夠不夠帥,今天編者就給大家推薦年輕人最愛的“三寶”
東風悅達起亞-起亞K5
指導價:15.98-24.88萬
新款K5在外觀上並沒有開刀闊斧的感覺,但在細節上做了提升,讓整車的細節、線條更為的精緻。“滿天星”的中網有一種奢華的格調,在視覺效果上非常的吸睛,在尾部方面並沒有做太多的改進,還是溜背式轎跑的設計,排氣依舊還是保留了雙邊共兩出的設計,更強調時尚、運動感。
在內飾設計上,K5更為簡潔,整个中控微微向駕駛員傾斜,能讓駕駛員在操作上更為簡單。按鍵的布局也十分平整,在做工用料上也在同級別中已經是中上的水準,整車的氛圍比上一代更加的簡約時尚。在空間方面,它也達到了B級車應有的水準,無論在腿部頭部空間都還有很大的余量,座椅的柔軟度恰到好處,在乘坐上的感受非常舒適。
K5提供2.0L、1.6T和2.0T、2.0L混動四款發動機可選,其中2.0L自然吸氣發動機配備的傳動系統為6擋手自一體在動力上更為平順,並不會有給你帶來很強的動力,適合斯斯文文的有為青年,而1.6T的渦輪增壓發動機,傳動系統配備的是7擋雙離合,在平順性不及2.0L發動機,但在動力上的響應性和油門的靈敏度會強上不少。2.0T渦輪增壓發動機在動力上的爆發更為明顯,最大功率180千瓦,最大扭矩350牛米,傳動系統配備的傳統的6擋手自一體,雖然6擋手自一體在響應性不會像雙離合那麼激進,但是因為發動機的動力性能夠足,駕駛快感也會更加直接。
北京現代-索納塔九
指導價:17.48-24.98萬
索納塔在外觀上的視覺衝擊更強,大嘴式的中網進氣格柵,有那麼有點點像奧迪的感覺,線條更為流暢、平緩,典型的韓系風格,整體外觀造型更加年輕、時尚。
在內飾上並沒有太多的花俏,而更多的是傳遞一種簡約時尚風,中控的設計十分大方得體,六邊形的銀色飾板,空調出風口有一塊長條的防碳纖維飾板點綴,營造出非常前衛的氣氛。在乘坐的空間上,完全達到了B級車應有的水準。索九有全景天窗、多功能方向盤、無鑰匙進入/啟動等豐富配置。
索納塔九提供了1.6T、2.0L和2.4L三款發動機,1.6T渦輪增壓發動機,最大功率132.4千瓦,最大扭矩265牛米,傳動系統方面只有1.6T車型是搭載7擋雙離合變速箱,2.0L和2.4L都是配備傳統的6擋手自一體,在動力的輸出上,1.6T車型前段的加速比2.0L、2.4L車型來得會更加直接,而在中後段就有種動力衰弱的感覺,在平順性方面,2.0L和2.4L車型更有優勢。
上汽通用雪佛蘭-邁銳寶
指導價:16.49-19.99萬
邁銳寶的外觀設計比上一代車型更加的精緻、車身的線條更加的飽滿,發動機微微隆起的線條,濃濃的美系的風格。前臉的設計很有層次感,大嘴式的進氣格柵,增強車頭的時尚感,整車的視覺感受,簡約但不簡單。
內飾上採用了“翼展式”中控設計,並且在一些部位用鍍鉻裝飾進行點綴,突出一定的精緻感,在按鍵的整體布局還是簡約大方,簡單而又有運動氛圍。在空間上並不是他的優勢,但在乘坐的舒適度非常高,因為底盤非常紮實,靜音也非常出眾。
邁銳寶提供了1.5T、1.6T和2.0L、2.4L四款發動機,傳動系統方面全系都配備6擋手自一體變速箱,其中1.5T車型最大功率125千瓦,最大扭矩252牛米,雖然排量小,但在動力的表現上比2.0L自然吸氣發動機更為突出。如更加追求動力的表現,1.6T、2.4L車型在輸出上更為優異,而行駛質感也非常高,底盤的調校非常紮實、從容。
編者點評:
面對競爭火熱的B級車市場,K5索納塔邁銳寶個性的風格,迎來不少年輕消費者的追捧,在外觀上和同級別的車型相比,不會顯得太平庸,而是更加的時尚動感,雖然都迎來了更新換代,但它們依然火爆。走在潮流尖端的年輕消費者來說,更加註重時尚,車的樣子要足夠的漂亮,這也是最基本的要求。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
※網頁設計最專業,超強功能平台可客製化
※別再煩惱如何寫文案,掌握八大原則!
所以小編這次就是要給大家說說艾5哪款車的性價比最高。下面兩個圖表分別是手動擋車型和自動擋車型。其中艾5標配主/副駕駛座安全氣囊、ESp、上坡輔助、后視鏡電動調節。所以如果預算不充足,即使最低配的艾5,也是可以入手的。
自主SUV異常火爆是眾所周知的,但是自主轎車在和合資轎車的對抗中一直出於劣勢,所以不少人都唱衰自主轎車。
但是事情總會有轉機的,只要廠家拿出有誠意的作品,銷量一定不會差的。比如奇瑞艾瑞澤5(本文簡稱艾5),這款起步價只有5.89萬的緊湊型轎車,要保證顏值和空間的情況下,竟然全系標配了ESp,正是因為如此厚道的配置,所以艾5的10月份銷量為16504輛。表現非常好。
艾5在今年3月18日上市,指導價為5.89-9.79萬,上市之後就取得了很大的反響,之所以引起巨大的關注,一是因為艾5的的原創性很高,在細節方面都突出了年輕化的設計理念。車頭造型飽滿,中網樣式類似“滿天星”,這樣的設計也使前格柵的層次感較為豐富。
二是因為艾5的配置確實不低。艾5的車身尺寸為4572*1825*1482mm,軸距為2670mm,標準的緊湊型轎車,不小的軸距極大的保證了車內空間。同時配置很高,即使是最低配,也是標配了ESp,從這一點可以看出這個企業還是挺實在的。
正是因為企業的“實在”,所以才得到了消費者的認可。但是當消費者去選擇艾5的時候,會發現密密麻麻一堆車型看起來就頭疼。所以小編這次就是要給大家說說艾5哪款車的性價比最高。下面兩個圖表分別是手動擋車型和自動擋車型。
其中艾5標配主/副駕駛座安全氣囊、ESp、上坡輔助、后視鏡電動調節。所以如果預算不充足,即使最低配的艾5,也是可以入手的。
通過圖表可以發現,撇開手動擋最低配和自動擋高配,其餘的手動擋和自動擋都是相互對應的,價格差了8000元,但是其它配置一樣的,所以相當於8000買個一台CVT變速箱,所以我們就以手動擋車型為例子進行分析。
通過上圖我們發現,雖然低配的性價比不低,但是和次低配領潮版比起來,性價比還是沒有領潮版高。
領潮版、智效領動版、領銳版相比起來,首先排除智效領動版,性價比最低。雖然領銳版售價已經接近7萬,但是多出的配置還是比較實用的。所以領銳版也有一定的性價比。
對於再高級別的領跑版和領臻版,無非就是多個氣囊、GpS,不過價格已經過高,對於艾5這款主打性價比的車子,顯然是不會受歡迎的。不過如果資金充足的話也可以選擇手動或者自動領臻版,安全配置比較豐富。
對於售價高達9.79萬的頂配車型-自動領尊版,更多的是為了提升品牌形象,幾乎完全沒有性價比。
綜上所述,領潮版的性價比最高了,其次是領銳版,同時最低配的手動領尚版性價比也不錯。其它車型的性價比不是很高。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整
※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!
※教你寫出一流的銷售文案?
※超省錢租車方案
※回頭車貨運收費標準
“全能MpV”奧德賽具備了魔方式的空間變換組合,可以根據不同場合的需求自由切換:除了可以乘坐7人的正常模式以外,還可以放倒部分第三排座椅,變為“休閑模式”或“超長模式”,更能將後排完全收起放平,變為“超大模式”。
在個人色彩越來越濃的今天
我們在職場上八面玲瓏,進退自如
但一轉身,面對與最親近的家人溝通
卻往往不知該如何應對……
11月的廣州依舊“熱情”高漲,而這份熱情也同樣延續到了11月12日在廣州舉辦的奧德賽非凡品鑒會活動現場。作為繼上海、北京之後又一場有別傳統的非凡品鑒會,坐鎮主場的奧德賽此番同樣延續了熱播綜藝《飯局的誘惑》節目熱潮,誠邀兩位金牌辯手現場與大家分享傳授說話之道,在欣賞奧德賽非凡魅力的同時,現場觀眾更是得到了智、情、局三商的全方位提升。
事實上,《飯局的誘惑》作為奧德賽與綜藝大咖馬東聯手打造的一檔綜藝節目,節目中高智商高情商的語言對壘令觀眾朋友大呼過癮。同樣的,以雙商詮釋自我產品特點的奧德賽在節目中頻繁亮相,更是成為嘉賓主持話梗里的經典“橋段”。也正因此,在非凡品鑒會上,奧德賽同樣將“說話的藝術”搬到了現場,在全方位展示自身產品實力的同時,更是將智、情、局三商的精髓應用到了日常生活之中。
延續高雙商開局 ,奧德賽掌控生活格局
Talk show環節,一如在前兩站中,“金牌辯手”們教會了大家如何應付生活中的各種尷尬,廣州站品鑒會上,馬薇薇與黃執中同樣為大家準備了新鮮的生活話題。
現場,金句女王馬薇薇首先與大家分享了如何在家庭生活中以“分”為貴,即在家庭關係中分清是“男權”還是“平權”為主;分清楚想要從原生家庭得到什麼就必須失去什麼;分清楚在自己組建的新家庭里是願意當主人還是當“孩子”。把握家庭話語權,例如馬薇薇提及在平權家庭中,面對出行問題時則必須共同承擔,在帶上自己父母的同時更要照顧到對方的父母。也正因此,像奧德賽這樣至少能夠容下6個人的車才是出行的必需品。
而事實上,作為一款7座MpV車型,奧德賽擁有2+2+3的座椅布局,在日常出行中,與一家三口的需求完美匹配,可以盡享第二排航空座椅的舒適體驗。即便是再帶上雙方父母,奧德賽的座位和空間也是綽綽有餘。這便是奧德賽對於家庭出行更為全面的考慮,也足以凸顯出其高情商的一面。
對於家庭生活的妥善處理,在網絡上一向以“情感專家”著稱的黃執中更是以男性視角深入剖析,教會大家如何利用情商照顧到身邊的每一個人。在談話中,黃執中提出:在遇到問題時不應關注事件本身,而是當事人雙方感覺的問題;在討論問題時不應站在對立面,而是轉換方式,一同面對問題;最終即便問題解決,也應該從對方得失心出發給予一定的安慰,讓對方知道她的委屈你能懂。簡而言之,黃執中用超高的情商詮釋了面對尷尬處境時如何照顧全局,細緻巧妙的處理也贏得了在場觀眾的掌聲。
正如黃執中說的那樣,奧德賽對於“掌控全局”也同樣非常在行。“全能MpV”奧德賽具備了魔方式的空間變換組合,可以根據不同場合的需求自由切換:除了可以乘坐7人的正常模式以外,還可以放倒部分第三排座椅,變為“休閑模式”或“超長模式”,更能將後排完全收起放平,變為“超大模式”。無論是全家外出的座位需要,亦或是商務接待需要的車內空間,奧德賽都能輕鬆掌控。
情景演繹扣人心弦,奧德賽解碼非凡亮點
與傳統品鑒會相比,非凡品鑒會的現場可謂處處不同。除了引人入勝的talk show環節,現場講師對產品的解讀也是別具一格。通過場景的植入與話題的點撥,講師從“撥、移、躺、藏、開”多角度深入,為現場觀眾生動解碼了奧德賽的非凡體驗點。
以“移”為例,在講解過程中,講師通過實際的例子為大家詮釋了奧德賽超低車門踏板設計的用意。原來,在設計之初,考慮到一些身着裙裝的女性能夠方便上下車,同時也照顧到老人小孩的乘坐便利,奧德賽在保證通過性的同時,將油箱做的更扁平,合理化配置的前提下,為乘客提供了最佳的上下車高度。奧德賽用高智商和高情商的雙商完美解決了問題。
亦動亦靜,全方位感受奧德賽非凡一面
靜態展示體驗部分,現場的一輛“特殊”展車令不少人眼前一亮。作為企業社會化責任的一部分,同時也作為車系派生車型的進一步完善,奧德賽福祉車的亮相無疑是場上的另一大看點。通過遙控二排可升降旋轉座椅,短短十幾秒內,行動不便的乘客無需自己挪動便可輕鬆實現上下車動作,方便之餘也再次體現出奧德賽全方位人性化的設計理念。
當然,除了靜態展示部分,品鑒會又怎少的了試駕環節。不同與上海站與北京站的路況,廣州站的試駕路線採用了“直線”加“調頭”的模式。試駕時,體驗者不僅能夠感受到“黃金動力組合”下奧德賽CVT無級變速箱的平順加速動力,同時,在調頭部分中更可感受奧德賽同級最小轉彎半徑的優勢。這樣的專項試駕也令不少體驗者印象深刻。
除了靜態展示和試乘試駕部分外,主辦方還為親臨現場體驗的來賓準備了奧德賽全能生活非凡禮遇。豐盛的現金禮遇和置換福利表現也令不少來賓現場簽訂購車意向。奧德賽的高局商則恰恰體現在此。
從職場到生活,從同事相處到家庭關係,奧德賽攜多位名嘴辯手與大家分享了職場人生中的說話之道,用一個個生動有趣的例子完美詮釋了高智商高情商的人生格局。創新、趣味、智慧、尊享,這就是奧德賽非凡品鑒會留給在場所有人的印象。而下一站深圳,活動即將迎來收官站,屆時,名嘴嘉賓又將有哪些辛辣犀利的話題與大家分享,奧德賽與你一同見證非凡本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※別再煩惱如何寫文案,掌握八大原則!
※網頁設計最專業,超強功能平台可客製化
※回頭車貨運收費標準
此概念車採用了跨界車的設計風格,前臉的設計感較強,中網採用了較為規整的網格格柵,並且進氣格柵與兩側的大燈相連融會貫通,整體很有科技感。下方的霧燈區域,摒棄了傳統的矩形或圓形燈組造型,轉而採用誇張的C型設計,辨識度很強,同時周邊的線條設計也增強了運動感。
隨着國內汽車市場的發展,自主品牌近年在設計上的提升是我們有目共睹的。在本次廣州車展上,不少企業將推出“高顏值”的車型,而在眾多高顏值的車型中最為吸引眼球的是我們自主品牌陸風旗下的一款定位時尚跨界緊湊型SUV概念車。
眾多的“高顏”車型中為什麼只看上了陸風這款車?難不成這款車擁有傲視群雄的品質?先別急聽給你好好扒一扒,拋開品質的變化之大暫且不論,單就外觀的設計以及家族式風格的蛻變,就能很明顯得看出如今陸風品牌的設計能力和品牌變化的巨大。
外觀設計的成功意味着什麼?難道只是換一個設計師設計造型那麼簡單?其實不然,通過對外觀設計風格的變化,我們能看出一款車型品牌的壯大、車企對市場方向的把控能力、對潮流市場引領的方向,這絕對是值得我們關注和探究的。
說了“辣么多”我們還是聊回陸風這款顏值擔當吧。
這款定位為時尚跨界緊湊型SUV概念車,就是陸風將於廣州車展亮相的一款重磅車型,並計劃於明年正式投入生產。講真,在第一眼看見陸風的這一款概念車的時候,完全就是被它的車身側面造型所吸引過去的,全然不知這竟然是一款自主品牌的SUV。
此概念車採用了跨界車的設計風格,前臉的設計感較強,中網採用了較為規整的網格格柵,並且進氣格柵與兩側的大燈相連融會貫通,整體很有科技感。下方的霧燈區域,摒棄了傳統的矩形或圓形燈組造型,轉而採用誇張的C型設計,辨識度很強,同時周邊的線條設計也增強了運動感。配合時尚的保險杠設計,提升了整車的運動及越野氣質,讓人感覺“野性”十足。
如果車頭造型還沒能打動你,那車身側面一定能讓你心花怒放。側面大角度傾斜的後窗玻璃與發動機蓋隆起的線條,使得這款車頗具美系車的肌肉感,搭配上巨大的輪圈和貫穿全車的側面雙腰線的設計,為車身帶來了修長的視覺效果,真是非常符合像這樣的年輕人口味。
動力方面據本次車展工作人員透露,未來量產車型動力方面,其匹配的1.5T缸內直噴汽油引擎及最新一代CVT變速器,將帶來絕佳的駕駛體驗,將在明年下半年正式上市。
【點評】:在2016年各大自品牌都發力SUV市場的激烈競爭下,陸風X7能在眾多競品中突圍而出尤為難得。從陸風汽車的產品布局來看,現階段將全部精力都投放到SUV產品中來,從這款定位時尚跨界緊湊型SUV概念車的亮相足矣看出,這是陸風集團聚萬千心血於一身的產品。
同時也能從產品看出,陸風汽車是具有極強自主設計能力的車企,在這個“顏”字當先的時代,高顏值勢必會成為本次車展各類新車的大趨勢,而這款概念車無疑是此次車展的高顏者,有興趣的朋友可以到廣州車展現場,陸風展台(1.2號館 2A01展位),一睹這款概念車的靚相。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※想知道最厲害的網頁設計公司"嚨底家"!
※別再煩惱如何寫文案,掌握八大原則!
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※回頭車貨運收費標準
※台中搬家公司費用怎麼算?