Android基础之六:多线程开发

  • 多线程开发为复杂的耗时处理功能提升了效率,同时也不影响UI界面的显示效果,是在Android开发或者Java开发中常常用到的一种开发机制
  • 首先理解多线程的概念:
    • 多线程并非真正的多个任务在同一时间点上并发执行,而是分时间片来执行,即同一个时间点上执行的任务只有一个,可是从一小段时间来看,倒是许多任务并发执行
    • 多线程须要注重资源的分配
    • 须要注意Java中多线程机制
    • 主线程:即应用的UI线程
    • 辅线程:即工做线程,不能直接操做UI
  • Android中的多线程
    • Handler类
      • post方法
        • post方法并无新起线程,仍然运行在UI线程中,其本质上仍是UI线程,只是是UI现成的子线程,能够优化UI操做性能
        • 与View自带的post方法原理相同,都是在UI子线程中操做UI变化
        • Handler handler=new Handler();
          handler.post(new Runnable() {
                @Override
                 public void run() {
                        //ToDo
                 }
          });
        • 注意:进行UI操做,例如修改UI控件属性等,虽然直接修改通常不会出现问题,可是若是在UI执行耗时操做时会形成卡顿,一般使用post来经过UI子线程来操做
      • sendMessage方法
        • post方法只适合在单独操做UI的状况下使用,若是其中涉及到耗时操做以及UI操做,例如:UI与Service通讯,根据Service返回的结果修改UI,Service一般是一个比较耗时的操做,在这种状况下就不能直接使用post将耗时操做放到UI线程中,而是须要开启辅线程
        • 辅线程是独立于UI线程以外的工做线程,在工做线程中可以处理复杂的业务逻辑计算等耗时操做,可是不能直接操做UI
        • 辅线程(工做线程)与UI线程之间的交互
          • UI线程中建立Handler
          • Handler handler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //UI 操做
                }
            };
          • 辅线程中建立Message消息,并向主线程的handler传递消息
          • Message message=new Message();
            message.setData(new Bundle());
            handler.sendMessage(message);
          • 这样就能够实现工做线程执行耗时操做,UI线程负责界面处理
    • HandlerThread类
      • HandlerThread能够另起新线程,但不能操做UI,属于工做线程
      • 经过HandlerThread的Looper建立的Handler使用post方法也不能操做UI,只有经过主线程的Looper建立的Handler才能操做UI,即Handler的构造方法中不传参时表示的是使用主线程的Looper建立实例
      • HandlerThread使用
        • 建立实例
        • HandlerThread ht = new HandlerThread("handler thread");
          ht.start();
        • 实例化后必须使用start启动
        • 经过HandlerThread实例的Looper建立Handler实例
        • Handler handler=new Handler(ht.getLooper());
        • 经过Handler实例进行post方法调用
        • handler.post(new Runnable(){//这里run()方法其实仍是在等ht.start()调用
              public void run(){
                  Log.e("当前线程:",Thread.currentThread().getName());//这里打印的会是handler thread
                  setTitle("哈哈");//这样一定报错
              }
          });
        • 在run中若是操做UI会直接报错,由于这个县城是工做线程,不能执行UI操做,而若是想要执行UI操做,须要经过sendMessage来实现,在UI线程中再实例化一个Handler实例,重写handlerMessage方法,而后在run中向该实例发送消息
        • 这样实现会发现比较繁琐并且低效,不建议使用这种方法,即HandlerThread不建议使用
        • 而且一个HandlerThread中建立的多个Handler,在post的时候并非并打的,而是顺序执行的
    • Java中建立线程方法
      • Java提供了通用的多线程类与接口,可以简单而直接建立工做线程,不须要使用HandlerThread建立一个handler
      • 经过new Thread(){run}.start();
      • new Thread(){
            @Override
            public void run() {
                super.run();
                //ToDo
            }
        }.start();
        • 该方法是经过匿名类来实例化Thread的子类实例的,在run中处理复杂操做,并发送消息到UI线程中,完成与UI线程通讯
      • 经过new Thread(Runnable).start();
      • new Thread(new Runnable() {
            @Override
            public void run() {
                
            }
        }).start();
        • 经过Runnable接口实例化Thread实例,与匿名类同样,只是两种不一样的实例化方法
    • AsyncTask异步任务
      • Android中提供一种异步任务类,可以实现简单的工做线程与主线程操做,是Handler、Message的结合,使用更加简单
      • 建立异步任务
        • 注意AsyncTask中的5个可重写方法
          • onPreExcute:是在异步任务执行前执行的操做,能够操做UI线程
          • doInBackground(params):在工做线程中执行的操做
          • onProgressUpdate(values):在工做线程执行过程当中若是须要操做UI,就能够在doInBackground中使用publicProgress();来广播进度,在onProgressUpdate中就会收到进度值
          • onPostExcute(retult):任务执行结束后调用,即将doInBackground中返回的结果传到该方法中
          • 在实例化AsyncTask的时候能够直接指定不一样方法中参数的类型,即AsyncTask是泛型类
          • 在整个过程当中只有一个方法doInBackground是在工做线层中运行的,其余三个方法都是在主线程中运行的
        • 实例化
        • AsyncTask<String,String,String> asyncTask=new AsyncTask<String, String, String>() {
              @Override
              protected void onPreExecute() {
                  super.onPreExecute();
              }
              @Override
              protected String doInBackground(String... params) {
                  return null;
              }
              @Override
              protected void onProgressUpdate(String... values) {
                  super.onProgressUpdate(values);
              }
              @Override
              protected void onPostExecute(String s) {
                  super.onPostExecute(s);
              }
          };
        • 与Thread+Handler+Message实现多线程比较
          • AsyncTask本质上就是Thread+Handler+Message的封装
          • 在Activity被从新建立(设备状态改变,例如屏幕方向变化引发的Activity重启)时,任务会被取消
          • 在线程池中只能容纳5个后台运行程序,再多会形成阻塞,这里表示的是经过AsyncTask建立的线程,用Thread建立的不算
          • 执行方式不一样,AsyncTask经过excute来执行,Thread经过start来执行
    • ExecutorService线程池
      • 线程池适合处理大量线程的操做,例如多线程加载1000张图片,多线程批量下载
      • 实例化线程池
        • 单线程
        • ExecutorService service=Executors.newSingleThreadExecutor();
        • 固定数量线程
        • ExecutorService service=Executors.newFixedThreadPool(10);
        • 动态线程
        • ExecutorService service=Executors.newCachedThreadPool();
      • 执行线程操做:
        • submit(Runnable):建立并执行一个工做线程
相关文章
相关标签/搜索