標籤: 網頁設計公司

  • 您的單例模式,真的單例嗎?

    您的單例模式,真的單例嗎?

          單例模式,大家恐怕再熟悉不過了,其作用與實現方式有多種,這裏就不啰嗦了。但是,咱們在使用這些方式實現單例模式時,程序中就真的會只有一個實例嗎?

          聰明的你看到這樣的問話,一定猜到了答案是NO。這裏筆者就不賣關子了,開門見山吧!實際上,在有些場景下,如果程序處理不當,會無情地破壞掉單例模式,導致程序中出現多個實例對象。

          下面筆者介紹筆者已知的三種破壞單例模式的方式以及避免方法。

    1、反射對單例模式的破壞

          我們先通過一個例子,來直觀感受一下

        (1)案例

      DCL實現的單例模式:

     1 public class Singleton{
     2     private static volatile Singleton mInstance;
     3     private Singleton(){}
     4     public static Singleton getInstance(){
     5         if(mInstance == null){
     6             synchronized (Singleton.class) {
     7                 if(mInstance == null){
     8                     mInstance = new Singleton();
     9                 }
    10             }
    11         }
    12         return mInstance;
    13     }
    14 }

      測試代碼:

     1 public class SingletonDemo {
     2 
     3     public static void main(String[] args){
     4         Singleton singleton = Singleton.getInstance();
     5         try {
     6             Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
     7             constructor.setAccessible(true);
     8             Singleton reflectSingleton = constructor.newInstance();
     9             System.out.println(reflectSingleton == singleton);
    10         } catch (Exception e) {
    11             // TODO Auto-generated catch block
    12             e.printStackTrace();
    13         }
    14     }
    15 }

      執行結果:

    false

          運行結果說明,採用反射的方式另闢蹊徑實例了該類,導致程序中會存在不止一個實例。

        (2)解決方案

          其思想就是採用一個全局變量,來標記是否已經實例化過了,如果已經實例化過了,第二次實例化的時候,拋出異常。實現代碼如下:

     1 public class Singleton{
     2     private static volatile Singleton mInstance;
     3     private static volatile boolean mIsInstantiated = false;
     4     private Singleton(){
     5         if (mIsInstantiated){
     6             throw new RuntimeException("Has been instantiated, can not do it again!");
     7         }
     8         mIsInstantiated = true;
     9     }
    10     public static Singleton getInstance(){
    11         if(mInstance == null){
    12             synchronized (Singleton.class) {
    13                 if(mInstance == null){
    14                     mInstance = new Singleton();
    15                 }
    16             }
    17         }
    18         return mInstance;
    19     }
    20 }

    執行結果:

     

         這種方式看起來比較暴力,運行時直接拋出異常。

     

    2、clone()對單例模式的破壞 

           當需要實現單例的類允許clone()時,如果處理不當,也會導致程序中出現不止一個實例。

        (1)案例

      一個實現了Cloneable接口單例類:

     1 public class Singleton implements Cloneable{
     2     private static volatile Singleton mInstance;
     3     private Singleton(){
     4     }
     5     public static Singleton getInstance(){
     6         if(mInstance == null){
     7             synchronized (Singleton.class) {
     8                 if(mInstance == null){
     9                     mInstance = new Singleton();
    10                 }
    11             }
    12         }
    13         return mInstance;
    14     }
    15     @Override
    16     protected Object clone() throws CloneNotSupportedException {
    17         // TODO Auto-generated method stub
    18         return super.clone();
    19     }
    20 }

      測試代碼:

     1 public class SingletonDemo {
     2 
     3     public static void main(String[] args){
     4         try {
     5             Singleton singleton = Singleton.getInstance();
     6             Singleton cloneSingleton;
     7             cloneSingleton = (Singleton) Singleton.getInstance().clone();
     8             System.out.println(cloneSingleton == singleton);
     9         } catch (CloneNotSupportedException e) {
    10             e.printStackTrace();
    11         }
    12     }
    13 }

    執行結果:

    false

      (2)解決方案:

         解決思想是,重寫clone()方法,調clone()時直接返回已經實例的對象

     1 public class Singleton implements Cloneable{
     2     private static volatile Singleton mInstance;
     3     private Singleton(){
     4     }
     5     public static Singleton getInstance(){
     6         if(mInstance == null){
     7             synchronized (Singleton.class) {
     8                 if(mInstance == null){
     9                     mInstance = new Singleton();
    10                 }
    11             }
    12         }
    13         return mInstance;
    14     }
    15     @Override
    16     protected Object clone() throws CloneNotSupportedException {
    17         return mInstance;
    18     }
    19 }

    執行結果:

    true

     

    3、序列化對單例模式的破壞

       在使用序列化/反序列化時,也會出現產生新實例對象的情況。

      (1)案例

          一個實現了序列化接口的單例類:

     1 public class Singleton implements Serializable{
     2     private static volatile Singleton mInstance;
     3     private Singleton(){
     4     }
     5     public static Singleton getInstance(){
     6         if(mInstance == null){
     7             synchronized (Singleton.class) {
     8                 if(mInstance == null){
     9                     mInstance = new Singleton();
    10                 }
    11             }
    12         }
    13         return mInstance;
    14     }
    15 }

        測試代碼:

     1 public class SingletonDemo {
     2 
     3     public static void main(String[] args){
     4         try {
     5             Singleton singleton = Singleton.getInstance();
     6             FileOutputStream fos = new FileOutputStream("singleton.txt");
     7             ObjectOutputStream oos = new ObjectOutputStream(fos);
     8             oos.writeObject(singleton);
     9             oos.close();
    10             fos.close();
    11 
    12             FileInputStream fis = new FileInputStream("singleton.txt");
    13             ObjectInputStream ois = new ObjectInputStream(fis);
    14             Singleton serializedSingleton = (Singleton) ois.readObject();
    15             fis.close();
    16             ois.close();
    17             System.out.println(serializedSingleton==singleton);
    18         } catch (Exception e) {
    19             e.printStackTrace();
    20         }
    21 
    22     }
    23 }

         運行結果:

    false

        (2)解決方案

        在反序列化時的回調方法 readResolve()中返回單例對象。

     1 public class Singleton implements Serializable{
     2     private static volatile Singleton mInstance;
     3     private Singleton(){
     4     }
     5     public static Singleton getInstance(){
     6         if(mInstance == null){
     7             synchronized (Singleton.class) {
     8                 if(mInstance == null){
     9                     mInstance = new Singleton();
    10                 }
    11             }
    12         }
    13         return mInstance;
    14     }
    15 
    16     protected Object readResolve() throws ObjectStreamException{
    17         return mInstance;
    18     }
    19 }

    結果:

    true

     

           以上就是筆者目前已知的三種可以破壞單例模式的場景以及對應的解決辦法,讀者如果知道還有其他的場景,記得一定要分享出來噢,正所謂“獨樂樂不如眾樂樂”!!!

           單例模式看起來是設計模式中最簡單的一個,但“麻雀雖小,五臟俱全”,其中有很多細節都是值得深究的。即便是本篇介紹的這幾個場景,也只是介紹了一些梗概而已,很多細節還需要讀者自己去試驗和推敲的,比如:通過枚舉方式實現單例模式,就不存在上述問題,而其它的實現方式似乎都存在上述問題!

     

           後記

           本篇參(剽)考(竊)了如下資料:

           高洪岩的《Java 多線程編程核心技術》

           博文:https://blog.csdn.net/fd2025/article/details/79711198

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

    【其他文章推薦】

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

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

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

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

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

    網頁設計最專業,超強功能平台可客製化

  • 漢蘭達提車等幾個月,不如看看這款2.0T+9AT的7座SUV

    漢蘭達提車等幾個月,不如看看這款2.0T+9AT的7座SUV

    0T+愛信6AT雖然動力數據不及大指揮官,但勝在穩定可靠。豐田在漢蘭達的動力調校上要比Jeep更為得心應手,低轉下的扭矩較為充沛,油門調校也有一貫日系車的風格,初段頗為靈敏。在零百成績方面,漢蘭達為9。13秒。儘管如此,在高速上再加速時,漢蘭達依舊顯得底氣十足。

    如果要買一輛7座中型SUV來作為家庭出行的首選,我想很多人都會第一時間想到漢蘭達。畢竟這麼多年的口碑擺在那裡,各方面的實力都較為均衡。奈何漢蘭達的產能有限,導致不少地區要等好幾個月,甚至加價才能提車。

    幾年前,福特推出銳界試圖撼動漢蘭達的地位,結果也只是成了不少人買不到漢蘭達,退而求其次的選擇。這回Jeep推出大指揮官也是試圖重新攪動這個市場,好好地打擊一下漢蘭達,那究竟指揮官有沒有這樣的實力呢?虎哥就為大家好好分析一下。

    從動力參數來看,大指揮官無論是最大馬力還是最大扭矩都比漢蘭達多不少,而且在整備質量方面,大指揮官比漢蘭達還要輕75kg,相當於一個成年男性的質量。不過,參數只是一個方面,更重要的還是動力匹配。

    大指揮官上的這副2.0T發動機與Giulia上的是同根同源,與之匹配的是ZF的9AT變速箱。日常駕駛時,能發現這副9AT還是偏向於平順的調校,低速蠕行時沒有什麼頓挫。

    這樣的調校會導致大指揮官在急加速時的換擋偏慢,好在這副2.0T的機器底氣較足,很多時候並不需要降太多的擋位便可以完成加速。大指揮官實測的零百成績能少於8秒,比漢蘭達要快不少。大指揮官在走一些顛簸路時,濾震不錯,有一定的厚實感,只是偏軟的彈簧導致剎車時容易點頭。

    漢蘭達的2.0T+愛信6AT雖然動力數據不及大指揮官,但勝在穩定可靠。豐田在漢蘭達的動力調校上要比Jeep更為得心應手,低轉下的扭矩較為充沛,油門調校也有一貫日系車的風格,初段頗為靈敏。

    在零百成績方面,漢蘭達為9.13秒。儘管如此,在高速上再加速時,漢蘭達依舊顯得底氣十足。底盤調校上,漢蘭達偏重於舒適,懸挂的工作也較為無感。走爛路時,漢蘭達的濾震厚實,無論是駕駛員還是乘客都坐得較為舒適。

    大指揮官的二三排

    從上面的對比表格不難看出,漢蘭達更傾向於做好第二排,所以第二排在最小時也不至於頂到前排。同時,全平的中央地板也為其加分不少。但是在第三排方面,明顯就不如大指揮官。

    漢蘭達的二三排

    雖然大指揮官的二排在最小和最大腿部空間上都不如漢蘭達,但是第三排在最好的情況下能調出四指的腿部空間。不過這還是有點雞肋,滿載時,不僅三排的人會坐得比較局促,連二排乘客也會隨之遭殃。

    從上面的配置對比來看,在相同指導價下,大指揮官的配置表現是要略微好於漢蘭達。儘管這款漢蘭達的售價高達30多萬,但依舊採用的是鹵素大燈,車窗一鍵升降也僅裝備於前排,這些都是不應該的。

    總結

    大指揮官的表現雖然不錯,但在這個級別消費者最需要的舒適和大空間方面,還是與漢蘭達拉不開距離。倒是在動力和配置方面,能展現出自己的優勢,這樣的表現與銳界有幾分相似。對於消費者而言,多一個選擇總歸還是一件好事情,但恐怕大指揮官還是無法撼動漢蘭達的地位。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

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

    ※台北網頁設計公司全省服務真心推薦

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

    ※推薦評價好的iphone維修中心

  • 月銷30000多輛,百公里6L油,這款10萬級家轎有這麼好?

    月銷30000多輛,百公里6L油,這款10萬級家轎有這麼好?

    在油耗方面,日產軒逸提供了1。6L以及1。8L兩款動力總成供消費者選擇,與之匹配的是一台CVT變速箱。而作為主銷車型的1。6L版本整體的動力表現並不會太過出色,但好在動力輸出平順,而且油耗水平做得相當出色,也是各大滴滴車主當中最火爆的車型之一。

    在10多萬的這個價位區間中,無論是合資品牌還是國產品牌都有着數十款車型供你選擇,而對於絕大多數消費者而言,都是希望能買到一台價格便宜、用得放心的車型,於是你會發現不少人都變得十分苦惱,究竟自己看上的車型到底值不值得購買呢?成為了當前最希望解決的一個難題。

    帶着問題,今天咱們先來討論一下日系三強當中熱度相當高的日產軒逸,究竟這一款車型的表現怎麼樣呢?

    在造型方面相信大家對其也是相當熟悉,也是採用當下最常規的日產家族式設計語言,造型設計較為年輕,符合到當下消費者的審美,而且每月均保持數萬台的銷量(3月份37672輛)也足以證明它受到眾多消費者所熱捧。

    有着沙發廠之稱的日產品牌,在軒逸上也做得相當出色,2700mm的軸距表現也賦予了它大空間舒適家用的亮點,而且車型本身也沒有明顯的短板,也是一款能夠滿足到各種家庭需求的車型。

    雖然很多人都認為合資車型總會出現價格高配置低的情況,而實際上隨着車型的更新換代,你會發現其實原本配置簡陋的合資車型已經變得更具競爭力;

    在配置水平方面日產軒逸雖說沒有過於突出的地方,在低配版本上配置可以說是相當低,所以也是不值得推薦的。但在主銷的中高配版本,豐富的配置水平也讓其性價比極高;而且在高配版本上頁新增加了併線輔助、車道偏離系統、主動剎車等科技含量比較高的配置,也是這個價位當中極其少有的存在。

    在油耗方面,日產軒逸提供了1.6L以及1.8L兩款動力總成供消費者選擇,與之匹配的是一台CVT變速箱。而作為主銷車型的1.6L版本整體的動力表現並不會太過出色,但好在動力輸出平順,而且油耗水平做得相當出色,也是各大滴滴車主當中最火爆的車型之一。

    而在保養方面,日系車最大的優勢便是保養費用不高,而且車型的耐久性相當高,開着不壞、用起來相當省心。

    優點:車型造型大氣、油耗出色、儲物和乘坐空間大,很適合家用

    缺點:沒有後排出風口、沒有標配倒車雷達、動力和操控較弱

    就像上文所說,軒逸更推薦考慮車價為13.78萬的1.6L尊享版或以上的車型版本,而車型本身的價格並不算太高,但是軒逸也是擁有着一個相當不錯的現金優惠,也幾乎可以用原車價去購車。

    關於軒逸而言,其實多年在市場上打滾也讓它在消費者心目當中有着非常不錯的口碑,舒適家用也是它的優勢之處,而車型本身並沒有明顯的短板,雖然表現平平但不失為一台及格的家用轎車。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※回頭車貨運收費標準

  • 同級最便宜,這款20多萬的超帥氣SUV車主卻說……

    同級最便宜,這款20多萬的超帥氣SUV車主卻說……

    0L混動最大馬力(pS):182/發動機:146 電動機:184最大扭矩(Nm):240/發動機:175 電動機:315變速箱:8DCT/E-CVT百公里加速(s):8。35/8。6百公里油耗(L):6。8/5車主百公里油耗(L):8。71/暫

    謳歌CDX肩負着在國內為謳歌品牌打開市場的重任,它具備極其前衛的設計風格,而且看到實車時你就會感受到其設計的精緻感!

    寬敞的空間,前衛設計讓它具有不錯的競爭力。而且它搭載一款1.5T高功率發動機,匹配一副8擋雙離合變速箱,動力系統匹配是高效的,它換擋平順,降擋的速度也相當快,動力表現可圈可點!下面我們就來看看這款豪華SUV車型的各方面表現怎麼樣吧!

    長寬高:4496*1840*1615mm

    軸距:2660mm

    定位:緊湊型SUV

    設計激進的謳歌CDX可謂是同級車型中的一股清流,前臉造型極其激進,鑽石形中網造型顯得相當有個性。同時車身線條緊湊,但車內卻能營造出足夠的乘坐空間。

    內飾方面它在細節處富有創意,造型類似“如意”的旋鈕擋把設計科技感強,而內飾的用料也是到位的。值得一提的是這套內飾的按鍵布局簡約、合理,方向盤上的按鍵也具備不錯手感,在行車過程中操作便利!

    發動機:1.5T/2.0L混動

    最大馬力(pS):182/發動機:146 電動機:184

    最大扭矩(Nm):240/發動機:175 電動機:315

    變速箱:8DCT/E-CVT

    百公里加速(s):8.35/8.6

    百公里油耗(L):6.8/5

    車主百公里油耗(L):8.71/暫本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

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

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

    網頁設計最專業,超強功能平台可客製化

  • 都是30萬德系轎車,頂配邁騰和奧迪A4L到底差多少?

    都是30萬德系轎車,頂配邁騰和奧迪A4L到底差多少?

    其實邁騰多出來的配置不止這些,還有二十多項,全部寫出來太長,故略去。低配的奧迪A4L採用了低功率的2。0T發動機,最大馬力是190匹,最大扭矩是320牛•米。頂配的邁騰使用的2。0T發動機賬面數據更好,220匹的最大馬力和350牛•米的最大扭矩均優於A4L。

    隨着平台化,規模化生產的普及,很多大集團都會在自己的普通品牌和豪華品牌上通用零件,但是定價卻差了幾萬,那麼這幾萬的差價真的如大家所說,是LOGO的差異嗎?同一個集團,應該買TA的普通品牌高配車型還是豪華品牌的低配車型比較划算?

    今天,我們來對比一下大眾邁騰的380TSI 旗艦版和奧迪A4L的40TFSI 進取版,看看哪個更值得買。

    邁騰和奧迪A4L的外觀是同一個風格的兩份答卷。邁騰的橫貫式前臉把大燈連接起來,從視覺上來看顯得更寬更低矮。今天對比的邁騰380TSI 旗艦版配備的是18寸輪轂,所以邁騰的側面看上去更加大氣一些。

    奧迪A4L則是在原有的六邊形格柵的家族設計元素上再下功夫,把大燈、格柵、車身線條設計得再銳利一些,所以奧迪A4L的外觀顯得更加年輕。不過這17寸的輪轂嘛,說實話不是很能襯托出A4L的檔次,建議後期更換。

    這一局,邁騰略勝。

    這一代的邁騰是歐版帕薩特直接拿來生產的,所以這一代邁騰的風格反而是繼承了上一代帕薩特的商務風。在邁騰上,木紋飾板貫穿整个中控台,空調出風口被設計得更高,所以空間更加寬闊。奧迪A4L的內飾以科技感為主要設計導向,奧迪A4L 30TSI 進取版採用中控台採用了銀色拉絲面板,中控屏採用懸浮式設計。可惜的是低配車沒有使用全液晶显示屏,空調面板也不是高配的那款金屬質感控制面板。所以質感稍顯不足。

    這一局,也是邁騰勝出。

    無論是邁騰還是奧迪A4L,引進國內后,都進行了不同程度的加長,邁騰的軸距為2871mm,比海外版增加了80mm,奧迪A4L的軸距是2908mm,比海外版增加了88mm。雖然奧迪A4L的軸距比邁騰要長一點,但是乘坐空間方面,邁騰比奧迪A4L要寬敞一點。這是因為邁騰是MQB(發動機橫置平台)的產物,而奧迪A4L是MLB(發動機縱置平台)的產物。發動機橫置的結構比較緊湊,占乘坐空間較少,所以邁騰的乘坐空間比奧迪A4L稍微大一點。

    這一局,因為兩者的差距微乎其微,所以判定兩者打成平手。

    在配置上,邁騰完勝沒什麼懸念。其實邁騰多出來的配置不止這些,還有二十多項,全部寫出來太長,故略去。

    低配的奧迪A4L採用了低功率的2.0T發動機,最大馬力是190匹,最大扭矩是320牛•米。頂配的邁騰使用的2.0T發動機賬面數據更好,220匹的最大馬力和350牛•米的最大扭矩均優於A4L。從加速成績來看,邁騰比奧迪A4L更好,但也只是半秒的差距。奧迪A4L的發動機有AVS可變氣門升程技術和混合噴射技術。這兩項技術都可以提高燃油經濟性,所以從用戶反饋的數據來看,奧迪A4L比邁騰節油不少。

    所以這局,也只能判五五開。

    說到舒適性方面奧迪A4L的前後懸挂都使用了五連桿獨立懸挂,而邁騰則採用了前麥弗遜獨立懸挂后多連桿獨立懸挂的組合。這不僅是因為成本,還因為邁騰使用的MQB佔據了機艙空間,所以無法布局多連桿懸挂。麥弗遜式獨立懸挂有個缺點,那就是上下運動的時候對車輪外傾角變化明顯,而車輪外傾角變化會影響操縱的穩定性。所以,為了安全性考慮,麥弗遜懸挂一般都會比較硬。而使用五連桿的奧迪A4L可以把懸挂調得軟一些,所以奧迪A4L的濾震更好。在加上在隔音材料方面,豪華品牌比普通品牌的投入會更大。

    所以舒適性方面,奧迪A4L完勝邁騰是沒什麼懸念的。

    總結:縱觀兩車各個方面的對比,互有勝負。豪華品牌的車不是只掛着一個LOGO就賣這麼貴,如果你坐過邁騰后再坐A4L,你確確實實能夠感受到豪華車帶給你的那種舒適感,高級感。但是在靜態體驗的時候,邁騰的頂配版可以說是完虐奧迪A4L了。所以,我建議,如果你打算購買一台商務車,邁騰的頂配版更加合適。如果只是買來自用,奧迪A4L值得考慮。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

    南投搬家公司費用需注意的眉眉角角,別等搬了再說!

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

  • 花25.88萬買漢蘭達的人看見榮威RX8會相當後悔?

    花25.88萬買漢蘭達的人看見榮威RX8會相當後悔?

    通過尺寸對比表,我們可以看出榮威RX8的三圍比漢蘭達要更大一些,軸距也比漢蘭達長60mm,營造出充足的7座空間。而且榮威RX8的第三排的膝部/頭部空間比漢蘭達大一拳,全幅靠背的採用舒適性更好。230mm同級稱冠的第二排座椅可調行程以及特有的Easy–Entry一鍵放倒功能,進出第三排的便利性更高。

    談起7座的SUV,大家都會聯想到充沛的乘坐空間、良好的通過性等標籤,它們擁有着極高的實用性,在生活方式日益多樣化的今天已成為汽車消費升級的首選,漢蘭達可以說是其中最熱門的車型之一,但是7座SUV車型之間的競爭越來越激烈,全新打造的車型越來越多,漢蘭達不得不面臨一位強勁對手發起的挑戰!

    它就是來自上汽榮威的“全領域大7座豪華SUV”車型榮威RX8!它是一款基於上汽新一代IS(智能化SUV)平台打造,具備“ALL-DRIVE”智能全領域駕駛系統,也擁有寬敞7座空間的重點車型!而這兩款車型在價格上有所重疊,到底榮威RX8能不能戰勝目前7座SUV界最火車型呢?虎哥就來和大家一探究竟!

    不得不和大家先嘮嗑一下車型的價格,因為榮威RX8已經在北京車展正式上市,虎哥認為其售價富有誠意,吸引力絕對不低,給予消費者選擇的空間也更多。

    咱們選取售價為22.88萬的榮威RX8 2018款 30T 智聯網四驅至尊版車型和指導價為25.88萬的豐田漢蘭達2.0T四驅精英版進行直接對比。

    先來對比外觀造型,榮威RX8的前臉採用了“律動”設計語言,造型富有力量感。全LED騰雲大燈科技感強,視覺也相當舒展,4顆透鏡式LED燈源組成的獵戶座星雲霧燈,也顯得炯炯有神。

    (注:拍攝視頻車型為2017款漢蘭達)

    榮威RX8的車身還具備黃金分割設計短前懸長后懸的豪華四驅車身比例,看上去具備動感,側面也刻畫出強而有力的輪包曲面。尾部設計橫向舒展,它具備內切燕尾、梯形的尾門的設計特點,比較有意思的是定音錘尾燈造型帶有“一錘定音”的寓意,細節處理值得仔細欣賞!

    新款漢蘭達的外觀設計在原有基礎上有所升級,它進氣格柵的面積得到擴大,但是車身輪廓仍舊屬於中庸的設計風格。

    視覺上略顯沉悶,而大燈造型的變化不大,它融入了LED日間行車燈,相比榮威RX8的全LED燈組顯得精緻感不足。車尾的造型敦實,造型飽滿但精緻感略顯不足。

    榮威RX8品牌家族化設計相當舒展、座艙採用環繞式設計富有層次感、體現出精緻豪華也兼具優雅的設計風格。用料相當考究,大面積皮質軟包與淡雅木紋飾板帶來良好觸感,10.1英寸中控大屏也富有科技感,細節處理也進一步提升了精緻感!

    而漢蘭達的內飾質感則顯得比較遜色,它中控布局簡潔明了,採用的軟質材料不少,看上去比較大氣。但是軟包面積不及榮威RX8,6.1英寸中控屏多媒體娛樂系統也顯得有些小氣。

    在大家相當關心的配置方面,榮威RX8拉開了明顯的優勢!值得一提的是在用戶舒適性營造方面它十分到位,無線充電、真皮座椅、主駕駛電動調節、前排座椅加熱+通風、第二排座椅加熱、大面積採光的全景天窗、獨立式空氣凈化器它均有配備!

    而且科技配備也已相當齊全,它配備有車機手機雙向WIFI、AI人工智能語音系統、主動導航系統、智能操作系統、虛擬儀錶、loT手機遠程車控系統等潮流前端的科技配備,配置方面的優勢十分明顯!

    通過尺寸對比表,我們可以看出榮威RX8的三圍比漢蘭達要更大一些,軸距也比漢蘭達長60mm,營造出充足的7座空間。而且榮威RX8的第三排的膝部/頭部空間比漢蘭達大一拳,全幅靠背的採用舒適性更好!230mm同級稱冠的第二排座椅可調行程以及特有的Easy–Entry一鍵放倒功能,進出第三排的便利性更高。漢蘭達第二排僅有150mm的移動距離,便利性有待提高。

    榮威RX8採用了BBA豪華品牌供應商德國Bader的頂級頭層小公牛皮座椅,而且還應用階梯式劇院座椅布局,每排乘客能享受舒適坐姿、視野開闊,並且NVH靜音水準較高,還配備大採光面積全景天窗。

    舒適配置全面,榮威RX8的前排擁有電動調節、主駕迎賓記憶、遠程座椅加熱、三檔加熱和通風等功能,第二排乘客也能享受座椅加熱功能,這功能在冬天相當實用!而漢蘭達則採用織物座椅,缺乏座椅加熱、通風功能,前排座椅沒有沒有電動調節,實用性不及榮威RX8。

    榮威RX8搭載縱置布局的“藍芯”2.0TGI缸內直噴渦輪增壓發動機,它具備全鋁缸體、雙可變氣門正時技術、渦輪增壓等高效科技,輸出224馬力最大功率、360牛米最大扭矩,動力輸出優於漢蘭達。

    與之匹配的是一款縱置愛信6速手自一體變速箱,動力輸出具備平順性、高效率的特點,這讓榮威RX8具備9.1秒的百公里加速和9.1L/100km綜合油耗的出眾表現!

    此外榮威RX8全系標配雙活塞浮動式制動卡鉗和陶瓷剎車片,這讓它的100-0km/h制動距離僅38米,要知道這是一款大尺寸的7座SUV車型,日常駕駛富有底氣!而某主流汽車媒體實測的漢蘭達剎車距離已超過41米,與榮威RX8有着不少差距。

    咱們先來看看硬件配備,榮威RX8採用高強度非承載式車身、雙叉臂獨立前懸架+五連桿后懸架,車身剛性高、抗扭能力強。它還具備較大后傾角設定,比起採用承載式車身設計的漢蘭達更能適應各種道路情況!

    而且榮威RX8公路駕駛時擁有良好的操控性、舒適性,它還搭載全時四驅系統和專業級中央、後橋差速鎖,可實現2驅和4驅鎖止!自動机械後橋限滑差速器在左右車輪速差超過120轉/分鐘時會自動鎖死,在複雜路面脫困能力高。

    漢蘭達則屬於承載式車身的城市SUV,採用的是基於前橫置的適時四驅系統,而且它僅有中央差速器鎖止功能,通過性不強,更適合市區路段。

    而且在四驅系統標定這一重要的軟實力方面,榮威RX8 無疑更加全面,下面咱們通過一個表格來詳細對比:

    榮威RX8帶有六大地形駕駛模式,在各種路況上適應能力強不少,而且雪地、越野、低速這三個駕駛模式能針對複雜的越野路面,實用性比漢蘭達高不少。

    榮威RX8搭載全新一代互聯網汽車智能系統-,即基於AliOS的斑馬智行解決方案,各項功能符合時下潮流,實用性強!在硬件上榮威RX8搭載10.1英寸高清中控屏和7英寸虛擬儀錶,显示清晰,操控更加便利,提升駕駛安全性。同時也提供了車機手機雙向WiFi和基礎服務、基本流量終身免費。

    而在這一價位中的漢蘭達只有6.1英寸多媒體娛樂系統,導航、有手機映射、聯網功能欠奉,功能性上落後於時代。

    寫在最後:經過全面的對比,咱們可以發現榮威RX8的外觀設計、內飾豪華度、科技感、配置豐富程度、乘坐空間、複雜路面適應性能、四驅系統全面性上都具備優勢,其實這也在意料之中,現在車型迭代迅速,作為全新車型的榮威RX8明顯具有後來居上之優勢,也極有潛力成為7座SUV中最有競爭力的車型!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

  • 要成為合格的女司機,最大的挑戰是什麼?

    要成為合格的女司機,最大的挑戰是什麼?

    可是,要完成這一次挑戰,我必須要有一台車。這次和我一起挑戰的,是全新昂科威28T頂配車型,2。0T發動機搭配9AT變速箱,擁有260匹馬力,還配備了CDC主動懸挂。2。0T發動機符合我對動力跟經濟性的需求。相比以前,全新的9AT變速箱也足夠聰明,足以應付多種路況。

    大家好,我是小喬,說真的,我有點害怕。

    作為一個女司機,我覺得我的駕駛技術算挺好了,但為什麼,我的知名程度,遠遠不如那個長得跟我差不多的Jacky呢?

    到底是“7200干它”成就了他,還是他成就了“7200干它”,這個問題,在我腦海中迴旋,如同先有雞還是先有蛋的生物史拷問,令我疑惑不已。終於,我決定卧薪嘗膽,直接跟他當面對質爆紅的真諦!

    Jacky面對我的質疑,嘴角微微上揚,說到:“既然你誠心誠意想要爆紅,那我就大發慈悲地成全你, 別克SUV強者挑戰之旅,這個對精神以及體力都有極大考驗的活動,就決定讓你參加了!“

    挑戰內容

    挑戰一:體能挑戰:限時挑戰3公里高空棧道。優秀的司機必須擁有強壯的體能!

    挑戰二:耐力測試,獨自跑完4個小時高速全程,鍛煉作為司機的集中力和耐久力。

    挑戰三:膽量挑戰:攀登懸崖天梯,鍛煉司機膽大心細的危急情況處理能力。

    挑戰四:險中求勝:考驗司機越野路面的駕駛能力。

    手拿這份挑戰清單,我感到一絲恐懼,但誓要成為女車神的我,不會輕易認輸!

    可是,要完成這一次挑戰,我必須要有一台車。這次和我一起挑戰的,是全新昂科威28T頂配車型,2.0T發動機搭配9AT變速箱,擁有260匹馬力,還配備了CDC主動懸挂。

    2.0T發動機符合我對動力跟經濟性的需求;相比以前,全新的9AT變速箱也足夠聰明,足以應付多種路況;它的懸架還能主動變化,公路、越野我都能舒舒服服。這一次挑戰,我勢在必得。

    想知道到底Jacky給小喬的挑戰有多可怕?讓小喬這個沒心沒肺的女人都感到驚慌,而她又能否順利完成任務?趕緊點開視頻看一看!

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

    【其他文章推薦】

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

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

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

    ※超省錢租車方案

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

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

  • 用python做時間序列預測九:ARIMA模型簡介

    用python做時間序列預測九:ARIMA模型簡介

    本篇介紹時間序列預測常用的ARIMA模型,通過了解本篇內容,將可以使用ARIMA預測一個時間序列。

    什麼是ARIMA?

    • ARIMA是’Auto Regressive Integrated Moving Average’的簡稱。
    • ARIMA是一種基於時間序列歷史值和歷史值上的預測誤差來對當前做預測的模型。
    • ARIMA整合了自回歸項AR和滑動平均項MA。
    • ARIMA可以建模任何存在一定規律的非季節性時間序列。
    • 如果時間序列具有季節性,則需要使用SARIMA(Seasonal ARIMA)建模,後續會介紹。

    ARIMA模型參數

    ARIMA模型有三個超參數:p,d,q

    • p
      AR(自回歸)項的階數。需要事先設定好,表示y的當前值和前p個歷史值有關。
    • d
      使序列平穩的最小差分階數,一般是1階。非平穩序列可以通過差分來得到平穩序列,但是過度的差分,會導致時間序列失去自相關性,從而失去使用AR項的條件。
    • q
      MA(滑動平均)項的階數。需要事先設定好,表示y的當前值和前q個歷史值AR預測誤差有關。實際是用歷史值上的AR項預測誤差來建立一個類似歸回的模型。

    ARIMA模型表示

    • AR項表示
      一個p階的自回歸模型可以表示如下:

      c是常數項,εt是隨機誤差項。
      對於一個AR(1)模型而言:
      當 ϕ1=0 時,yt 相當於白噪聲;
      當 ϕ1=1 並且 c=0 時,yt 相當於隨機遊走模型;
      當 ϕ1=1 並且 c≠0 時,yt 相當於帶漂移的隨機遊走模型;
      當 ϕ1<0 時,yt 傾向於在正負值之間上下浮動。

    • MA項表示
      一個q階的預測誤差回歸模型可以表示如下:

      c是常數項,εt是隨機誤差項。
      yt 可以看成是歷史預測誤差的加權移動平均值,q指定了歷史預測誤差的期數。

    • 完整表示

      即: 被預測變量Yt = 常數+Y的p階滯后的線性組合 + 預測誤差的q階滯后的線性組合

    ARIMA模型定階

    看圖定階

    差分階數d
    • 如果時間序列本身就是平穩的,就不需要差分,所以此時d=0。
    • 如果時間序列不平穩,那麼主要是看時間序列的acf圖,如果acf表現為10階或以上的拖尾,那麼需要進一步的差分,如果acf表現為1階截尾,則可能是過度差分了,最好的差分階數是使acf先拖尾幾階,然後截尾。
    • 有的時候,可能在2個階數之間無法確定用哪個,因為acf的表現差不多,那麼就選擇標準差小的序列。
    • 下面是原時間序列、一階差分后、二階差分后的acf圖:

      可以看到,原序列的acf圖的拖尾階數過高了,而二階差分后的截尾階數過小了,所以一階差分更合適。

    python代碼:

    import numpy as np, pandas as pd
    from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
    import matplotlib.pyplot as plt
    plt.rcParams.update({'figure.figsize':(9,7), 'figure.dpi':120})
    
    # Import data : Internet Usage per Minute
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/wwwusage.csv', names=['value'], header=0)
    
    # Original Series
    fig, axes = plt.subplots(3, 2, sharex=True)
    axes[0, 0].plot(df.value); axes[0, 0].set_title('Original Series')
    plot_acf(df.value, ax=axes[0, 1])
    
    # 1st Differencing
    axes[1, 0].plot(df.value.diff()); axes[1, 0].set_title('1st Order Differencing')
    plot_acf(df.value.diff().dropna(), ax=axes[1, 1])
    
    # 2nd Differencing
    axes[2, 0].plot(df.value.diff().diff()); axes[2, 0].set_title('2nd Order Differencing')
    plot_acf(df.value.diff().diff().dropna(), ax=axes[2, 1])
    
    plt.show()
    
    AR階數p

    AR的階數p可以通過pacf圖來設定,因為AR各項的係數就代表了各項自變量x對因變量y的偏自相關性。

    可以看到,lag1,lag2之後,偏自相關落入了藍色背景區間內,表示不相關,所以這裏階數可以選擇2,或者保守點選擇1。

    MA階數q

    MA階數通過acf圖來設定,因為MA是預測誤差,預測誤差是自回歸預測和真實值之間的偏差。定階過程類似AR階數的設定過程。這裏可以選擇3,或者保守點選擇2。

    信息準則定階

    • AIC(Akaike Information Criterion)

      L是數據的似然函數,k=1表示模型考慮常數c,k=0表示不考慮。最後一個1表示算上誤差項,所以其實第二項就是2乘以參數個數。

    • AICc(修正過的AIC)
    • BIC(Bayesian Information Criterion)

    注意事項:

    • 信息準則越小,說明參數的選擇越好,一般使用AICc或者BIC。
    • 差分d,不要使用信息準則來判斷,因為差分會改變了似然函數使用的數據,使得信息準則的比較失去意義,所以通常用別的方法先選擇出合適的d。
    • 信息準則的好處是可以在用模型給出預測之前,就對模型的超參做一個量化評估,這對批量預測的場景尤其有用,因為批量預測往往需要在程序執行過程中自動定階。

    構建ARIMA模型

    from statsmodels.tsa.arima_model import ARIMA
    
    # 1,1,2 ARIMA Model
    model = ARIMA(df.value, order=(1,1,2))
    model_fit = model.fit(disp=0)
    print(model_fit.summary())
    

    中間的表格列出了訓練得到的模型各項和對應的係數,如果係數很小,且‘P>|z|’ 列下的P-Value值遠大於0.05,則該項應該去掉,比如上圖中的ma部分的第二項,係數是-0.0010,P-Value值是0.998,那麼可以重建模型為ARIMA(1,1,1),從下圖可以看到,修改階數后的模型的AIC等信息準則都有所降低:

    檢查殘差

    通常會檢查模型擬合的殘差序列,即訓練數據原本的序列減去訓練數據上的擬合序列后的序列。該序列越符合隨機誤差分佈(均值為0的正態分佈),說明模型擬合的越好,否則,說明還有一些因素模型未能考慮。

    • python實現:
    # Plot residual errors
    residuals = pd.DataFrame(model_fit.resid)
    fig, ax = plt.subplots(1,2)
    residuals.plot(title="Residuals", ax=ax[0])
    residuals.plot(kind='kde', title='Density', ax=ax[1])
    plt.show()
    
    

    模型擬合

    # Actual vs Fitted
    model_fit.plot_predict(dynamic=False)
    plt.show()
    

    模型預測

    除了在訓練數據上擬合,一般都會預留一部分時間段作為模型的驗證,這部分時間段的數據不參与模型的訓練。

    from statsmodels.tsa.stattools import acf
    
    # Create Training and Test
    train = df.value[:85]
    test = df.value[85:]
    
    # Build Model
    # model = ARIMA(train, order=(3,2,1))  
    model = ARIMA(train, order=(1, 1, 1))  
    fitted = model.fit(disp=-1)  
    
    # Forecast
    fc, se, conf = fitted.forecast(15, alpha=0.05)  # 95% conf
    
    # Make as pandas series
    fc_series = pd.Series(fc, index=test.index)
    lower_series = pd.Series(conf[:, 0], index=test.index)
    upper_series = pd.Series(conf[:, 1], index=test.index)
    
    # Plot
    plt.figure(figsize=(12,5), dpi=100)
    plt.plot(train, label='training')
    plt.plot(test, label='actual')
    plt.plot(fc_series, label='forecast')
    plt.fill_between(lower_series.index, lower_series, upper_series, 
                     color='k', alpha=.15)
    plt.title('Forecast vs Actuals')
    plt.legend(loc='upper left', fontsize=8)
    plt.show()
    

    這是在ARIMA(1,1,1)下的預測結果,給出了一定的序列變化方向,看上去還是可以的。不過所有的預測值,都在真實值以下,所以還可以試試看有沒有別的更好的階數組合。
    其實如果嘗試用ARIMA(3,2,1)會發現預測的更好:

    AUTO ARIMA

    通過預測結果來推斷模型階數的好壞畢竟還是耗時耗力了些,一般可以通過計算AIC或BIC的方式來找出更好的階數組合。pmdarima模塊的auto_arima方法就可以讓我們指定一個階數上限和信息準則計算方法,從而找到信息準則最小的階數組合。

    from statsmodels.tsa.arima_model import ARIMA
    import pmdarima as pm
    
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/wwwusage.csv', names=['value'], header=0)
    
    model = pm.auto_arima(df.value, start_p=1, start_q=1,
                          information_criterion='aic',
                          test='adf',       # use adftest to find optimal 'd'
                          max_p=3, max_q=3, # maximum p and q
                          m=1,              # frequency of series
                          d=None,           # let model determine 'd'
                          seasonal=False,   # No Seasonality
                          start_P=0, 
                          D=0, 
                          trace=True,
                          error_action='ignore',  
                          suppress_warnings=True, 
                          stepwise=True)
    
    print(model.summary())
    
    # Forecast
    n_periods = 24
    fc, confint = model.predict(n_periods=n_periods, return_conf_int=True)
    index_of_fc = np.arange(len(df.value), len(df.value)+n_periods)
    
    # make series for plotting purpose
    fc_series = pd.Series(fc, index=index_of_fc)
    lower_series = pd.Series(confint[:, 0], index=index_of_fc)
    upper_series = pd.Series(confint[:, 1], index=index_of_fc)
    
    # Plot
    plt.plot(df.value)
    plt.plot(fc_series, color='darkgreen')
    plt.fill_between(lower_series.index, 
                     lower_series, 
                     upper_series, 
                     color='k', alpha=.15)
    
    plt.title("Final Forecast of WWW Usage")
    plt.show()
    

    從輸出可以看到,模型採用了ARIMA(3,2,1)的組合來預測,因為該組合計算出的AIC最小。

    如何自動構建季節性ARIMA模型?

    如果模型帶有季節性,則除了p,d,q以外,模型還需要引入季節性部分:

    與非季節性模型的區別在於,季節性模型都是以m為固定周期來做計算的,比如D就是季節性差分,是用當前值減去上一個季節周期的值,P和Q和非季節性的p,q的區別也是在於前者是以季節窗口為單位,而後者是連續時間的。
    上節介紹的auto arima的代碼中,seasonal參數設為了false,構建季節性模型的時候,把該參數置為True,然後對應的P,D,Q,m參數即可,代碼如下:

    # !pip3 install pyramid-arima
    import pmdarima as pm
    # Seasonal - fit stepwise auto-ARIMA
    smodel = pm.auto_arima(data, start_p=1, start_q=1,
                             test='adf',
                             max_p=3, max_q=3, m=12,
                             start_P=0, seasonal=True,
                             d=None, D=1, trace=True,
                             error_action='ignore',  
                             suppress_warnings=True, 
                             stepwise=True)
    smodel.summary()
    

    注意這裏的stepwise參數,默認值就是True,表示用stepwise algorithm來選擇最佳的參數組合,會比計算所有的參數組合要快很多,而且幾乎不會過擬合,當然也有可能忽略了最優的組合參數。所以如果你想讓模型自動計算所有的參數組合,然後選擇最優的,可以將stepwise設為False。

    如何在預測中引入其它相關的變量?

    在時間序列模型中,還可以引入其它相關的變量,這些變量稱為exogenous variable(外生變量,或自變量),比如對於季節性的預測,除了之前說的通過加入季節性參數組合以外,還可以通過ARIMA模型加外生變量來實現,那麼這裏要加的外生變量自然就是時間序列中的季節性序列了(通過時間序列分解得到)。需要注意的是,對於季節性來說,還是用季節性模型來擬合比較合適,這裏用外生變量的方式只是為了方便演示外生變量的用法。因為對於引入了外生變量的時間序列模型來說,在預測未來的值的時候,也要對外生變量進行預測的,而用季節性做外生變量的方便演示之處在於,季節性每期都一樣的,比如年季節性,所以直接複製到3年就可以作為未來3年的季節外生變量序列了。

    
    def load_data():
        """
        航司乘客數時間序列數據集
        該數據集包含了1949-1960年每個月國際航班的乘客總數。
        """
        from datetime import datetime
        date_parse = lambda x: datetime.strptime(x, '%Y-%m-%d')
        data = pd.read_csv('https://www.analyticsvidhya.com/wp-content/uploads/2016/02/AirPassengers.csv', index_col='Month', parse_dates=['Month'], date_parser=date_parse)
        # print(data)
        # print(data.index)
        ts = data['value']
        # print(ts.head(10))
        # plt.plot(ts)
        # plt.show()
        return ts,data
    
    # 加載時間序列數據
    _ts,_data = load_data()
    # 時間序列分解
    result_mul = seasonal_decompose(_ts[-36:],  # 3 years
                                    model='multiplicative',
                                    freq=12,
                                    extrapolate_trend='freq')
    _seasonal_frame = result_mul.seasonal[-12:].to_frame()
    _seasonal_frame['month'] = pd.to_datetime(_seasonal_frame.index).month
    # seasonal_index = result_mul.seasonal[-12:].index
    # seasonal_index['month'] = seasonal_index.month.values
    print(_seasonal_frame)
    _data['month'] = _data.index.month
    print(_data)
    _df = pd.merge(_data, _seasonal_frame, how='left', on='month')
    _df.columns = ['value', 'month', 'seasonal_index']
    print(_df)
    print(_df.index)
    _df.index = _data.index  # reassign the index.
    print(_df.index)
    
    build_arima(_df,_seasonal_frame,_data)
    
    # SARIMAX Model
    sxmodel = pm.auto_arima(df[['value']],
    						exogenous=df[['seasonal_index']],
    						start_p=1, start_q=1,
    						test='adf',
    						max_p=3, max_q=3, m=12,
    						start_P=0, seasonal=False,
    						d=1, D=1, trace=True,
    						error_action='ignore',
    						suppress_warnings=True,
    						stepwise=True)
    sxmodel.summary()
    # Forecast
    n_periods = 36
    fitted, confint = sxmodel.predict(n_periods=n_periods,
    								  exogenous=np.tile(seasonal_frame['y'].values, 3).reshape(-1, 1),
    								  return_conf_int=True)
    index_of_fc = pd.date_range(data.index[-1], periods = n_periods, freq='MS')
    # make series for plotting purpose
    fitted_series = pd.Series(fitted, index=index_of_fc)
    lower_series = pd.Series(confint[:, 0], index=index_of_fc)
    upper_series = pd.Series(confint[:, 1], index=index_of_fc)
    
    # Plot
    plt.plot(data['y'])
    plt.plot(fitted_series, color='darkgreen')
    plt.fill_between(lower_series.index,
    				 lower_series,
    				 upper_series,
    				 color='k', alpha=.15)
    
    plt.title("SARIMAX Forecast of a10 - Drug Sales")
    plt.show()
    
    

    以下是結果比較:

    • 選擇ARIMA(3,1,1)來預測:
    • 選擇季節性模型SARIMA(3,0,1),(0,1,0,12)來預測:
    • 選擇帶季節性外生變量的ARIMA(3,1,1)來預測:

    ok,本篇就這麼多內容啦~,下一篇將基於一個實際的例子來介紹完整的預測實現過程,感謝閱讀O(∩_∩)O。

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

    【其他文章推薦】

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

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

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

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

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

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

  • 架構思考-業務快速增長時的容量問題

    架構思考-業務快速增長時的容量問題

    背景

    之前做過一個項目,數據庫存儲採用的是mysql。當時面臨着業務指數級的增長,存儲容量不足。當時採用的措施是

     

    1>短期解決容量的問題

    mysql從5.6升級5.7,因為數據核心且重要,數據庫主從同步採用的是全同步, 利用5.7并行複製新特性,減少了主從同步的延遲,提高了吞吐量。

     

    當時業務量高峰是2000TPS,5.6時可承受的最大TPS是3000,升級到5.7壓測可承受的最大TPD是5000.

     

    2>流量拆分,從根本上解決容量問題

    首先進行容量評估,通過對於業務開展規劃、活動預估,年底的容量會翻5倍。由於目前指數級增長的特性,數據庫要預留至少4倍的冗餘。

     

    要對數據庫進行擴容,因為我們已經使用的是最頂配的SSD物理機了,就算可以在linux內核層面對numa進行綁核和非綁核等測試調參優化性能,提升容量也很有限。注意:一般的業務系統numa綁核會提高性能,但是mysql等數據庫系統是相反的。

     

    所以垂直擴容不成功,就看看是否可以拆分流量。mysql流量拆分方式有x軸拆分(水平拆分)、y軸拆分(垂直拆分)、z軸拆分。

     

    其中y軸拆分(垂直拆分)就是目前都在說做垂直領域,就是在一個細分領域里做深入的意思。由此可以很容易的記住垂直拆分的意思就是按照業務領域進行拆分,專庫專用。實際上能按領域拆分是最理想的,因為這種拆分業務清晰;拆分規則明確;系統之間整合或擴展容易。但是因為當時的業務已經很簡單,y軸拆分已經沒有什麼空間,這種拆分不能達到擴容20倍的目的。

     

    z軸拆分近幾年沒有聽說過了,實際上大家也一直在用。這種方式是將一張大表拆分為子母表,就是分為概要信息和詳細信息。這種拆分方式對解決容量問題意義不大。

     

    比較可行的一個方案是水平拆分。就是常說的分庫分表。按照容量評估,數據庫水平拆分一拆十,根據業務特點找一個標準字段來進行取模。

     

    水平拆分一個技術點在於新老切換。

    採用的是數據庫雙寫的方式,採用異步確保性的補償型事務,發送實時和延遲兩個MQ,通過開關來控制以老數據為準還是新數據庫為準。開始時以老數據庫為準,觀察新老數據沒有一致性問題之後,在一個低峰期,關閉了系統入口,等數據庫沒有任何變更之後切換開關,再打開系統入口。

     

    問題

    對於容量問題,上面採用的是一次性拆分到位的方法。對於一個規模稍大的公司來講,10組物理機(1組包含1主N從)的成本還好。

    1>如果量級再次升級,需要每周增加10台數據庫才能支撐容量呢?

    2>並且對系統可用性還有強要求,1s的停機都不可以接受呢?

     

    解決方案分析

    垂直流量拆分

    首先我要分析的是每周增加10台數據庫這個容量是不是合理的。是否存在放大效應或者說可以減少對mysql這種昂貴資源的使用,轉為增加對HBase、Elasticsearch這種低成本高擴展性資源的使用呢?

     

    基於這個思路,我們需要梳理下是否有可垂直拆分的流量。比如正向流量和負向流量。所謂正向流量是指比如交易下單,負向流量就是取消訂單,包括已付款取消、未付款取消、已到貨取消、未到貨取消等等。實際上負向流量在總訂單里佔比很少,但是業務要比正向交易業務複雜。將正向和逆向拆分的一個主要優勢是分治思想,可以降低兩部分各自的複雜度。將流量拆分重心轉移到正向流量上。

     

    對於正向流量,一個業務比較常用的流量拆分思路是CQRS命令查詢分離,也就是常說的讀寫分離。如果讀流量大於寫流量。可以考慮能否將讀流量進一步拆分。拆分成實時和離線,將實時性要求不高的查詢走ES。ES的數據可以通過同步binlog變更獲得。

     

    另外一個思路是將數據庫按照歷史數據來拆分。就是數據庫里只保存一定時間內的實時數據。超過指定時間則進行數據歸檔。將數據歸檔到HBase等,一般對於歷史的查詢實時性要求也不是很高。

     

    垂直流量拆分可能遇到的問題

    以上方法都是只考慮問題1如果量級再次升級,需要每周增加10台數據庫才能支撐容量的方案。如果再考慮問題2並且對系統可用性還有強要求,1s的停機都不可以接受。就需要看上述方案可能會遇到的問題。

     

    拆分正向流量和負向流量、CQRS都需要改造,改造過程就需要過渡。過渡可以採用上面說的雙寫方式,觀察運行情況進行切換。切換過程中也可以不關閉流量。

     

    麻煩的是數據歸檔。因為數據歸檔后刪除數據庫的數據,變更生效時,針對innodb來說,意味着數據結構重建,頻繁IO。這會影響OLTP在線事務的處理。可以考慮按表來歸檔,控制操作頻率,控制單位時間內對IO的影響。

     

    分佈式關係型數據庫

    分佈式關係型數據庫本質上是通過增加代理等方式將分庫分表做的更加隱蔽。

     

    阿里巴巴分佈式關係數據庫(DRDS),前身是淘寶分佈式數據層(TDDL),核心就是用於分庫分表管理的代理層,宣稱可實現平滑擴容。

     

     

    擴容過程實際是物理數據遷移的過程,引擎層按照分庫遷移后的邏輯先在物理節點上建立新的分庫,然後保留一個時間點進行全量的數據遷移。完成全量遷移后,開始基於先前保留的時間點進行增量的數據追趕。當增量數據追趕到兩邊的數據幾乎一致時,對數據庫進行瞬時停寫,將最後的數據追平,引擎層進行分庫邏輯的路由切換,路由規則切換完成后就完成了核心的擴容邏輯,整個切換過程在毫秒級別完成。

     

    因為整個過程是毫秒級,所以可以做到業務層沒有感知,等多就是看到擴容過程中請求延時增加了不到1s。從原理上來說是可行的。

     

    NOSQL解決方案

    像這麼大的數據量一個很好的參考是12306。12306採用的是Geode。它是有數據庫功能的內存數據網格(In-Memory Data Grid,IMDG)。其重要特性是

     

    1)集群內存總容量,現在Geode可以實現單個節點200-300GB內存,總集群包含300個節點的大型集群,因此總容量可以達到90TB左右的級別。

     

    2)Geode集群功能非常強大,實現了內存中數據Shard分佈,自動管理,集群故障自動恢復,自動平均分佈等一系列企業級的功能,而且有自帶的集群間數據同步功能。

     

    3)在CAP原理下(不了解的話可以百度一下CAP不可能三角),Geode可以保證集群內數據的強一致性,注意是真正的強一致性而不是最終一致性,再加上分區可用性,因此是一個CP型的產品,可以提供統一的數據視圖,支持高併發下的acid事務。

     

    採用新的解決方案最大問題是平滑過渡,平滑過渡方面我還是覺得上面提到的數據庫雙寫方式安全可靠。

     

    系統共建的解決方案

    如果達到我所說的量級,基本上在一個行業中是處於垄斷地位的。並不是一家純的互聯網公司。這種公司可以採用和互聯網大廠合作的方式、用已經有這方面經驗的大廠,來根據自己內部系統的特性共建一套合適自己的定製化數據庫。

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

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

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

    ※台北網頁設計公司全省服務真心推薦

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

    ※推薦評價好的iphone維修中心

  • UniRx精講(二):獨立的 Update &UniRx 的基本語法格式

    UniRx精講(二):獨立的 Update &UniRx 的基本語法格式

    獨立的 Update

    在 UniRx 簡介的時候,筆者講了一種比較麻煩的情況:就是在 MonoBehaviour 的 Update 中摻雜了大量互相無關的邏輯,導致代碼非常不容易閱讀。

    這種情況我們平時在項目開發中非常常見,代碼如下:

    private void Update()
    {
    	if (A)
    	{
    		...
    	}
    
    	if (B)
    	{
    		...
    		if (D)
    		{
    			...
    		}
    		else {}
    	}
    
    	switch (C)
    	{
    		...
    	}
    
    	if (Input.GetMouseButtonUp(0))
    	{
    		...
    	}
    }
    

    Update 方法中代碼冗長,而且干擾視線,非常影響閱讀。

    而使用 UniRx 則可以改善這個問題。

    void Start()
    {
    	// A 邏輯,實現了 xx
    	Observable.EveryUpdate()
    			.Subscribe(_ => 
    			{
    				if (A)
    				{
    					...
    				}
    			}).AddTo(this);
    	
    
    	// B 邏輯,實現了 xx
    	Observable.EveryUpdate()
    			.Subscribe(_ =>
    			{
    				if (B)
    				{
    					...
    					if (D)
    					{
    						...
    					}
    				else {}
    				}
    			}).AddTo(this);
    
    	// C 邏輯,實現了 xx
    	Observable.EveryUpdate()
    			.Subscribe(_ =>
    			{
    				switch (C)
    				{
    					...
    				}
    			}).AddTo(this);
    
    	// 鼠標點擊檢測邏輯
    	Observable.EveryUpdate()
    			.Subscribe(_ => {
    			{
    				if (Input.GetMouseButtonUp(0))
    				{
    					...
    				}
    			}).AddTo(this);
    }
    

    雖然在代碼長度上沒有任何改善,但是最起碼,這些 Update 邏輯互相之間獨立了。
    狀態跳轉、延時等等這些經常在 Update 里實現的邏輯,都可以使用以上這種方式獨立。

    使用 UniRx 可以對我們工程中的代碼進行了改善,而筆者接觸 UniRx 之後,就再也沒有使用過 Update 方法了。

    不過以上的這種 UniRx 使用方式,是比較初級的,而這種使用方式,隨着對 UniRx 的深入學習,也會漸漸淘汰,因為等我們入門之後,會學習更好的實現方式。

    今天的內容就這些。

    知識地圖

    UniRx 的基本語法格式

    在之前的兩篇文章中,我們學習了 UniRx 的 Timer 和 Update 這兩個 API,但是對代碼的工作原理還沒有進行過介紹。在這篇文章中,我們就來試着理解一下 UniRx 的代碼工作原理及 UniRx 的基本語法格式。

    先搬出來第一篇文章中 Delay 的實現代碼:

    /****************************************************************************
     * http://liangxiegame.com liangxie
     ****************************************************************************/
     
    using System;
    using UniRx;
    using UnityEngine;
    
    namespace UniRxLesson
    {
    	public class DelayExample : MonoBehaviour
    	{
    		private void Start()
    		{
    			Observable.Timer(TimeSpan.FromSeconds(2.0f)).Subscribe(_ =>
    			{
    				Debug.Log("延時兩秒"); 
    				
    			}).AddTo(this);
    		}
    	}
    }
    

    代碼中的 Observable.XXX().Subscribe() 是非常經典的 UniRx 格式。只要理解了這種格式就可以看懂大部分的 UniRx 的用法了。

    首先解決代碼中的詞彙問題:

    • Observable:可觀察的,是形容詞,它形容後邊的詞(Timer)是可觀察的,我們可以直接把 Observable 後邊的詞理解成發布者。
    • Timer:定時器,名詞,被 Observable 修飾,所以是發布者,是事件的發送方。
    • Subscribe:訂閱,是動詞,它訂閱誰呢?當然是前邊的 Timer,這裏可以理解成訂閱者,也就是事件的接收方。
    • AddTo:添加到,這個我們暫時不用理解得太深刻,只需要知道它是與 MonoBehaviour 進行生命周期綁定即可。

    以上的代碼,連起來則是:可被觀察(監聽)的.Timer().訂閱()
    理順了之後應該是:訂閱可被觀察的定時器。

    其概念關係很容易理解。

    • Timer 是可觀察的。
    • 可觀察的才能被訂閱。
    Observable.XXX().Subscribe();
    

    這行代碼我們可以理解為:可被觀察(監聽)的 XX,註冊。

    以上筆者從發布者和訂閱者這個角度進行了簡單的介紹,以便大家理解。
    但是 UniRx 的側重點,不是發布者和訂閱者這兩個概念如何使用,而是事件從發布者到訂閱者之間的過程如何處理。
    所以這兩個點不重要,重要的是兩點之間的線,也就是事件的傳遞過程。

    這裏先不說得太深入,在入門之後,會用很大的篇幅去深入介紹這些概念的。

    今天的 UniRx 的基本語法格式的介紹就到這裏,我們下一篇再見,拜拜~

    知識地圖

    更多內容
    QFramework 地址:https://github.com/liangxiegame/QFramework
    QQ 交流群:623597263
    涼鞋的主頁:https://liangxiegame.com/zhuanlan
    關注公眾號:liangxiegame 獲取第一時間更新通知及更多的免費內容。

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

    【其他文章推薦】

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

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

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

    南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

    ※超省錢租車方案