Android : thread的结束,挂起和恢复

在Android应用的开发过程中, 我们有时候需要通过创建一个新的线程去完成一些任务。例如,我们去进行搜寻动作,如果搜寻比较费时,我们就需要通过进度条来提示用户搜寻的进展情况,避免用户认为发生了死机。此时进度条的刷新就需要另外一个线程去实现。

但是这里有一个误区 : 有些人在多线程开发的时候会错误的认为,如果我们从创建线程的Activity中退出(该Acitivity被销毁),则在该Activity中创建的自定义线程也会被销毁。其实这是大错特错了。

实践证明,上述情况下,创建的线程并不会自动销毁,而是仍然在后台默默无闻地执行,直到自行结束。Android的这种设计是无可厚非的。从理论上来解释,应用的最小执行单位是线程,最小资源单位是进程,一个进程可以包含多个线程,而多个线程共享同一个所属进程的资源。因此,个人理解Android的应用其实就是一个进程,而里面的每个UI, Activity就是从属这个进程的线程,从一个Activity进入另外一个Activity本质就是将之前的线程挂起,然后创建后面的线程。退出也是同理。自定义线程也是遵循这个原则的。除非去控制某个线程结束,否则只有当该现程执行完毕或者所属的进程被销毁,该线程才会真正的结束。

综上,当我们在自定义线程还没有执行完毕的情况下,需要结束相关动作的时候,我们就要认为地去结束相关线程。例如,在搜寻过程中,我们不想去继续搜寻,而退出了搜寻功能,此时我们就需要去结束自定义的搜寻线程。如果不这样会可能造成严重错误。例如,我们反复进入搜寻功能去搜寻,在搜寻未结束时退出,然后再进入。这种情况下,由于之前的自定义线程并未结束,而之后又会有多个新搜寻线程被创建执行,很容易导致临界区冲突,从而导致设备当机。

那么我们如何控制这些自定义线程呢?以下笔者将给与详细说明。

 

一. 线程的结束

 

其实,通过帮助文档,我们可以知道,Android的线程类本身就提供了一些公共方法去结束线程。

void  destroy()    

This method is deprecated. Not implemented.

synchronized final void  stop(Throwable throwable)

This method is deprecated. because stopping a thread in this manner is unsafe and can leave your application and the VM in an unpredictable state.

final void  stop()

This method is deprecated. because stopping a thread in this manner is unsafe and can leave your application and the VM in an unpredictable state

 

        但是,通过说明我们可以看到,这些方法Android本身都是不推荐使用的,通过这种方式结束线程是不安全的,可能会让我们的应用退出,并且会让虚拟机处于一种无法预料的状态。那么开发过程中,在合情合理的需求中,我们怎么去安全的结束指定的自定义线程呢?笔者来救赎了。

1.    我们可以在自定义线程类中定义一个布尔私有变量,并且初始化为假,用于记录线程的执行状态。

2.    在run函数开始,设置该变量为真,表示线程进入执行状态。

3.    在run函数结束位置,设置该变量为假,表示线程进入结束状态。

4.    在run的线程执行部分,我们可以找一些锲点,对该变量进行判断,如果为真则继续执行,否则退出run函数。

5.    在自定义线程类中再提供一个公共函数,该函数的作用是将上述状态变量设置为假。

     这样,当自定义线程执行还未结束时,我们就可以通过调用5中的方法将线程安全结束。

        思想的本质就是,既然我们不能安全强制结束线程,那我们就让它安全地提前退出。效果是一样的。

程序实例 :

class SearchThread extends Thread {

    private Object mPauseLock;
    private boolean mPauseFlag;

    public SearchThread() {
        mPauseLock = new Object();
        mPauseFlag = false;
    }

    public void onPause_thread() {
        synchronized (mPauseLock) {
            mPauseFlag = true;
        }
    }

    public void onResume_thread() {
        synchronized (mPauseLock) {
            mPauseFlag = false;
            mPauseLock.notifyAll();
        }
    }

    private void pauseThread() {
        synchronized (mPauseLock) {
            if (mPauseFlag) {
                try {
                    mPauseLock.wait();
                } catch (Exception e) {
                    Log.v("thread", "fails");
                }
            }
        }
    }

    @Override
    public void run() {
        //---线程执行部分,仅仅举例为了说明-----
        while (!mPauseFlag) {
            try {
                pauseThread();
                if (err_video)
                    mHandler.obtainMessage(ERROR_HANDLE)
                            .sendToTarget();
                Thread.sleep(5000);
                Log.e("robin debug", "thread.go");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}在Android中有时我们会遇到类似这样的问题,我要绘制一个曲线图,但是我想让它可以被暂停和继续。首先,绘图肯定得用到多线程的知识。java的Thread类中自带suspend和resume两个方法来实现线程的暂停和恢复,可惜的是,现在已经不被建议使用了,而且,就算你用了,也没什么卵用,根本没效果,哈哈(这就很尴尬了!)

网上查了不少资料(在这里感谢网上一些博客的指导了),经过修改,哈,保证绝对可以用。废话不多说,先贴代码:

    private class MyThread extends Thread {
        private final Object lock = new Object();
        private boolean pause = false;

         /**
         * 调用这个方法实现暂停线程
         */
        void pauseThread() {
            pause = true;
        }

        /**
         * 调用这个方法实现恢复线程的运行
         */
        void resumeThread() {
            pause = false;
            synchronized (lock) {
                lock.notifyAll();
            }
        }

        /**
         * 注意:这个方法只能在run方法里调用,不然会阻塞主线程,导致页面无响应
         */
        void onPause() {
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void run() {
            super.run();
            try {
                int index = 0;
                while (true) {
                // 让线程处于暂停等待状态
                    while (pause) {
                        onPause();
                    }
                    try {
                        System.out.println(index);
                        Thread.sleep(50);
                        ++index;
                    } catch (InterruptedException e) {
                        //捕获到异常之后,执行break跳出循环
                        break;
                    }
                }
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
    }

如上代码所示,我们使用一个锁对象来实现线程的等待和继续运行,这里需要注意,使用myThread.wait()是不行的,不信可试试。还有就是onPause()方法一定只能在run方法里面执行,不然就变成让主线程等待了。

怎么启动?这个应该很简单吧,我们在别的类中执行:

MyThread my = new MyThread();
Thread thread = new Thread(my);
thread.start();

暂停的话,只需执行:

pauseThread();
恢复线程运行:

resumeThread();束的话直接用线程对象thead.interrupt();就行,这时会触发InterruptedException异常,
我们在while循环的这个异常捕获的catch中写break;就可以跳出循环,线程自动就会结束



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值