Android 多線程優(yōu)化那些事

背景

年初開發(fā)了一個項目河胎,項目中有這樣一個需求,需要每隔一秒鐘向服務(wù)器發(fā)起一次狀態(tài)信息查詢指令虎敦,在這個過程中偶爾會主動發(fā)起一次狀態(tài)信息修改的指令(PS:因為服務(wù)器的處理能力有限游岳,必須間隔一秒才能發(fā)送命令,否則指令將不會被執(zhí)行)其徙。本來不是什么大問題胚迫,但是由于開發(fā)人員從事android開發(fā)時間較短,多線程用得也不多唾那,所以看似簡單的問題晌区,最后使得整個項目出現(xiàn)了較大的性能問題。下面主要講講如何一步步的優(yōu)化過程通贞。(本文適合初學(xué)者,大拍瘴澹可以繞道前行)昌罩。

優(yōu)化前

以下是功能部分代碼

    public void sendOrderToServer(final byte[] data) {
        Thread thread = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                order_queue.offer(data);//將指令放入隊列中
                if (null != order_queue && order_queue.size() != 0) {
                    synchronized (lock) {
                        while (order_queue.size() != 0) {
                            try {
                                  byte[] orderData = order_queue.poll();//取出隊首指令
                                  int dataLength = orderData.length; 
                                  if (dataLength > 0) {
                                      //發(fā)送指令到服務(wù)器
                                  }
                                  try {
                                      Thread.sleep(1000);//等待一秒鐘,然后執(zhí)行下一條指令
                                  } catch (InterruptedException e) {
                                      e.printStackTrace();
                                  }
                              } catch (IOException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  }
             }
          });
          thread.start();
     }

代碼很簡單灾馒,相信大家都能看懂是什么意思茎用,閱讀下來好像也沒什么太大問題。模擬器運行一遍睬罗,沒有問題轨功,各項數(shù)據(jù)顯示正常。然后信心滿滿安裝到真機上容达,拍拍手古涧,歐??,搞定花盐∠刍可惜理想是美好的菇爪,現(xiàn)實是殘酷的,分分鐘啪啪啪打臉柒昏。app運行不到一分鐘凳宙,整個界面就開始卡頓了,操作屏幕毫無反應(yīng)职祷。這是為啥呢 氏涩??有梆?

然后認真閱讀了一下代碼是尖,發(fā)現(xiàn)里面用到了synchronized (lock)同步鎖,筆者為什么要這樣寫淳梦,估計是考慮到指令需要間隔一秒鐘才能發(fā)送析砸,又要保證指令是按序的。由于app每次發(fā)送命令都需要調(diào)用sendOrderToServer方法爆袍,并創(chuàng)建新的線程首繁。這就出現(xiàn)了一個問題,除了第一個線程能獲取到同步鎖陨囊,其他的線程都無法獲取到弦疮,因為order_queue隊列永遠不會為空。那么其他線程都相當于死鎖蜘醋,都無法執(zhí)行后面的代碼胁塞,也就不能釋放占用的系統(tǒng)資源。這樣線程不停的創(chuàng)建压语,系統(tǒng)資源被一點點消耗掉啸罢,最后造成界面卡頓。既然問題找到了胎食,那就好辦了扰才,其實優(yōu)化方法有很多,下面只是其中一種厕怜。

優(yōu)化后

public void sendOrderToServer(final byte[] data) {
         order_queue.offer(data);
}

private class WriteThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (true) {
                if (null != order_queue && order_queue.size() != 0) {
                        byte[] orderData = order_queue.poll();
                        if (null != orderData) {
                            int dataLength = orderData.length;
                            if (dataLength > 0) {
                                //發(fā)送指令到服務(wù)器
                            }
                        }
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

只創(chuàng)建一個WriteThread對象衩匣,里面運行一個while (true)的循環(huán),發(fā)送指令時只需要調(diào)用sendOrderToServer方法粥航,往order_queue隊列中加入指令就好琅捏。

總結(jié)

1、項目中使用多線程加鎖時递雀,需要注意不要造成死鎖柄延。
2、如果需要創(chuàng)建大量的線程映之,請使用線程池來管理拦焚,減少線程創(chuàng)建的開銷蜡坊,以及資源的浪費。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赎败,一起剝皮案震驚了整個濱河市秕衙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌僵刮,老刑警劉巖据忘,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異搞糕,居然都是意外死亡勇吊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門窍仰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汉规,“玉大人,你說我怎么就攤上這事驹吮≌胧罚” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵碟狞,是天一觀的道長啄枕。 經(jīng)常有香客問我,道長族沃,這世上最難降的妖魔是什么频祝? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮脆淹,結(jié)果婚禮上常空,老公的妹妹穿的比我還像新娘。我一直安慰自己盖溺,他們只是感情好窟绷,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咐柜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪攘残。 梳的紋絲不亂的頭發(fā)上拙友,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音歼郭,去河邊找鬼遗契。 笑死,一個胖子當著我的面吹牛病曾,可吹牛的內(nèi)容都是我干的牍蜂。 我是一名探鬼主播漾根,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼踪危,長吁一口氣:“原來是場噩夢啊……” “哼虐呻!你這毒婦竟也來了斋竞?” 一聲冷哼從身側(cè)響起卢厂,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤亮隙,失蹤者是張志新(化名)和其女友劉穎奕谭,沒想到半個月后瞧栗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灯荧,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡僵井,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年陕截,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片批什。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡农曲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出驻债,到底是詐尸還是另有隱情乳规,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布却汉,位于F島的核電站驯妄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏合砂。R本人自食惡果不足惜青扔,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翩伪。 院中可真熱鬧微猖,春花似錦、人聲如沸缘屹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轻姿。三九已至犁珠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間互亮,已是汗流浹背犁享。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留豹休,地道東北人炊昆。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凤巨。 傳聞我的和親對象是個殘疾皇子视乐,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,100評論 1 32
  • 引用自多線程編程指南應(yīng)用程序里面多個線程的存在引發(fā)了多個執(zhí)行線程安全訪問資源的潛在問題。兩個線程同時修改同一資源有...
    Mitchell閱讀 1,990評論 1 7
  • 在一個方法內(nèi)部定義的變量都存儲在棧中敢茁,當這個函數(shù)運行結(jié)束后佑淀,其對應(yīng)的棧就會被回收,此時卷要,在其方法體中定義的變量將不...
    Y了個J閱讀 4,417評論 1 14
  • Object C中創(chuàng)建線程的方法是什么渣聚?如果在主線程中執(zhí)行代碼,方法是什么僧叉?如果想延時執(zhí)行代碼奕枝、方法又是什么? 1...
    AlanGe閱讀 1,739評論 0 17
  • Java-Review-Note——4.多線程 標簽: JavaStudy PS:本來是分開三篇的瓶堕,后來想想還是整...
    coder_pig閱讀 1,649評論 2 17