国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Activity已銷毀,創(chuàng)建的線程未回收問(wèn)題

2019-11-09 15:05:00
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

今天在做新模塊測(cè)試時(shí)發(fā)現(xiàn)了一個(gè)嚴(yán)重的問(wèn)題,當(dāng)一個(gè)activity開(kāi)啟一個(gè)線程時(shí),如果當(dāng)前activity調(diào)用finish()函數(shù)不會(huì)關(guān)閉當(dāng)前創(chuàng)建的線程。對(duì)于每個(gè)新建activity,如果activity中的線程發(fā)生內(nèi)存泄漏。在java中線程時(shí)垃圾回收機(jī)制的根源,也就是說(shuō),在運(yùn)行系統(tǒng)中DVM虛擬機(jī)總會(huì)使硬件持有運(yùn)行狀態(tài)的進(jìn)程的引用,結(jié)果導(dǎo)致處于運(yùn)行狀態(tài)的線程將永遠(yuǎn)不會(huì)回收。因此你必須為你的后臺(tái)線程實(shí)現(xiàn)銷毀邏輯。

先說(shuō)下問(wèn)題出現(xiàn)的場(chǎng)景,我在一個(gè)activity中創(chuàng)建一個(gè)線程,輪詢?nèi)グl(fā)送請(qǐng)求,正常情況下是沒(méi)什么問(wèn)題的,先看下問(wèn)題代碼:

@OverridePRotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    new Thread(new Runnable() {        @Override        public void run() {            while (1 == 1) {                try {                    Thread.sleep(1000);                    Log.i("-------", "running");                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }).start();}這時(shí)看Log日志是正常打印,然后我按返回鍵退出當(dāng)前應(yīng)用,發(fā)現(xiàn)Log日志還在打印,問(wèn)題出現(xiàn)了,線程被沒(méi)有被回收,而且當(dāng)你再次返回到應(yīng)用時(shí),會(huì)再在后臺(tái)創(chuàng)建一個(gè)線程,兩個(gè)線程同時(shí)在跑。

在Java中強(qiáng)制關(guān)閉線程是非安全性操作,這時(shí)我們要為自己的線程添加判斷條件,相關(guān)代碼如下:

private MyThread myThread;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    myThread = new MyThread();    myThread.start();}private class MyThread extends Thread {    private boolean stop = false;    @Override    public void run() {        super.run();        while (!stop) {            try {                Thread.sleep(1000);                Log.i("-------", "running");            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public void close() {        stop = true;    }}@Overrideprotected void onDestroy() {    super.onDestroy();    myThread.close();}這樣,當(dāng)activity銷毀時(shí)走destroy函數(shù)然后調(diào)用Thread的close,讓線程退出輪詢,保證了線程安全回收。

還有另外一個(gè)思路來(lái)讓線程可以及時(shí)回收,我們知道context對(duì)象與activity是綁定的,我們可以實(shí)例application來(lái)暫存當(dāng)前context與當(dāng)前context進(jìn)行比較,我們可以優(yōu)化上面的代碼,具體代碼如下:

自定義application用來(lái)暫存context對(duì)象:

public class MyApplication extends Application {    static Context appContext;    @Override    public void onCreate() {        super.onCreate();    }    public static void setContext(Context context) {        appContext = context;    }}讓線程去做context比較,這樣我們就可以忽略activity的生命周期:

private MyThread myThread;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    MyApplication.setContext(this);    myThread = new MyThread(this);    myThread.start();}private class MyThread extends Thread {    private boolean stop = false;    private Context context;    public MyThread(Context context) {        this.context = context;    }    @Override    public void run() {        super.run();        while (context == MyApplication.appContext) {            try {                Thread.sleep(1000);                Log.i("-------", "running");            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

大功告成。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 江山市| 饶阳县| 府谷县| 板桥市| 于都县| 临夏市| 锡林郭勒盟| 牡丹江市| 上饶市| 凉山| 临清市| 米脂县| 宁城县| 广汉市| 吉林市| 九江县| 娄底市| 隆昌县| 海门市| 星子县| 印江| 连城县| 凉城县| 周至县| 大安市| 冷水江市| 互助| 邵阳市| 留坝县| 玛纳斯县| 阜阳市| 惠东县| 博兴县| 牙克石市| 顺义区| 台东市| 武宣县| 保定市| 洛浦县| 密云县| 泗阳县|