Android中的多线程的实现方式

不少Android初学者可能觉得,说到多线程就是Handler相关的知识。其实这种理解非常片面。本篇文章详细总结一下android中的多线程。

多线程的几种实现方式:

  1. extends Thread:
class MyFirstThread extends Thread{
        @Override
        public void run() {
            super.run();
            Log.d(TAG,"thread id + " + Thread.currentThread());
        }
    }

主线程中对其调用:

MyFirstThread t = new MyFirstThread();
t.start();
  1. implements Runnable:
class MySecondThread implements Runnable {
        @Override
        public void run() {
            Log.d("xlq111","thread id + " + Thread.currentThread());
        }
    }

主线程中对其调用时,需要将其放到Thread中:

Thread t = new Thread(new MySecondThread());
t.start();
  1. FutureTask (此方式用的较少)
Callable<String > callable = new Callable<String>() {
        @Override
        public String call() throws Exception {
            Log.d("xlq111","task thread = " + Thread.currentThread());
            return Thread.currentThread().toString();
        }
    };

FutureTask<String> task = new FutureTask<>(callable);
Thread t = new Thread(task);
t.start();
  1. AsycTask (这个很熟悉)
class MyThirdThread extends AsyncTask<URL,Integer,Long>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Long doInBackground(URL... urls) {
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Long aLong) {
            super.onPostExecute(aLong);
        }
    }

调用方式:

MyThirdThread thread = new MyThirdThread();
thread.execute();
  1. 线程池(此篇先不介绍)

线程间的通信:

此时便是多线程的核心机制:Handler机制。此时几个先介绍几个类:
Handler:用于发送和处理Message和Runnable对象;
MessageQueue:消息队列,用于存放通过Handler发布的消息;
Looper:用于从MessageQueue中取出消息(Message)对象,并发送给Handler处理;
Message:消息的类型,里面包含几个实例对象

各个类之前的对应关系:
一个Handler对应一个Looper,一个Looper可以对应多个Handler。
一个Looper 只拥有一个MessageQueue,所以多个Handler可以共享一个MessageQueue,从而达到消息共享的目的。

通信方式:Handler有两种工作体系来完成子线程handler的发送
post:可以post一个Runnable对象到MessageQueue中,存在下 列几种post方法
post(Runnable);
postDelayed(Runnable,long);
postAtTime(Runnable,long);
sendMessage:可以Send一个Message对象到MessageQueue对,存在如下方法
sendMessage(Message);
sendEmptyMessage(int);
sendMessageDelayed(Message,long);
sendMessageAtTime(Message,long);

主线程handler的接收:
复写handleMessage方法,实现接收到数据之后的操作。

Handler造成的内存溢出(OOM):

看代码:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
           mTextView.setText("");
        }
    };

这种常见的Handler的创建过程,会有可能造成内存溢出。原因是因为mHandler是非静态匿名内部类的实例,持有对外部类Activity的引用,当Activity走OnDestroy方法时,如果此时MessageQueue中还有Message没有处理完,Message对handler持有引用,handler对activity持有引用,导致Activity无法被GC回收,导致内存泄漏。

正确的写法应该是:

private static class MyHandler extends Handler {

        private WeakReference<Context> reference;   

        public MyHandler(Context context) {
            reference = new WeakReference<>(context);//这里传入activity的上下文
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }

由于handler持有的是activity的弱引用,弱引用可以被GC回收。另外还未处理完的Message,可以在onDestroy方法中调用mHandler.removeCallbacksAndMessages(null)来将Message清空,所以以上写法,不会造成OOM。

多说几句:

  1. 如果要在子线程中创建Looper或者主线程中的Looper为空,必须使用Looper.prepare()方法来创建Looper;

  2. 创建Message时,推荐使用Message.obtain()或者Handler.obtatinMessage,因为通过这两个方法得到的对象是从对象回收池中得到,也就是说是复用已经处理完的Message对象,而不是重新生成一个新对象,这样对内存开销较小。

就写到这,如有遗漏或错误,请指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,186评论 0 23
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,539评论 25 709
  • 从澳洲回来,果岭夏荷诗词文学社的老师和朋友们要给我接风。经过小飞社长的预约,昨夜成行。 小飞社长说要AA制的,诗社...
    独孤行_苍茫阅读 910评论 6 0
  • 此刻,我聽到大空調發出的轰轰聲,小女兒叫我喝水,喝完她蓋蓋子的咣咣聲,大女兒叫我的聲音,處理完讓她們去睡覺。有她倆...
    張蕾馥阅读 123评论 0 0
  • 姓名:朱非凡 公司:杭州美登贸易 上海361期《六项精进》反省二组 【日精进打卡第78天】 【知~学习】 《六项精...
    朱非凡阅读 161评论 0 0