(本文由言念小文原创,转载请注明出处)
一 前言
有Android开发经验的同学都清楚,UI的更新必须在主线程中进行,且主线程不能被阻塞,否则系统ANR异常。我们往往做一些数据处理是耗时操作,必须要在子线程中进行,然后再将处理后的数据切换到主线程去更新UI,这便是线程切换。
线程切换的本质是“数据的切换”,即将数据从一个线程传递到另一个线程。
二 案例描述
老风格,先给出场景案例,然后通过线程切换实现该案例。
案例:在线程A中调用api发送一段数据data,data最终通过线程切换由线程B执行数据处理动作。
三 线程切换基本原理
所谓线程切换,本质就是“数据在线程间切换”,即将一个线程A中的数据,传递到另一个线程B执行数据处理操作。基于以上认知,比较自然的实现逻就是:将线程A中的数据进行拷贝,线程B获取到拷贝数据,然后进行处理,如下图所示。
四 案例实现代码
首先创建一个DataHandler类,该类中定义了数据拷贝方法和数据处理线程。在DataHandler中定义了一个用于数据副本存放的成员变量mData;外部模块可通过sendData()将数据拷贝到DataHandler中;在DataHandler构造中初始化数据处理线程(线程B);该线程重写的run()方法中用一个while循环不停查询数据副本mData的值,当检测到mData有数据时,则执行数据处理动作,数据处理完成后,将数副本mData清空。这样便实现了将其他外部线程中的数据切换到线程B中处理。
public class DataHandler { // 数据副本 private String mData; public DataHandler() { initSwithThread(); } /** * 发送数据,供外部调用 * @param data */ public void sendData(String data) { // 拷贝数据 mData = data; } private void initSwithThread() { new Thread(new Runnable() { @Override public void run() { while(true) { if(null != mData && mData.length() > 0) { System.out.println("process data, run in thread : " + Thread.currentThread().getName() + ", data = " + mData); // 数据发送后,清除数据副本mData mData = null; } // 为了能够清晰看清结果这里让thread休眠1s try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "ThreadB").start(); } }
测试类ThreadTest中创建线程A,然后在A中调用DataHandler实例的数据拷贝方法sendData()将数据切换到线程B中处理。
public class ThreadTest { public static DataHandler mHandler; public static void main(String[] args) { mHandler = new DataHandler(); Thread threadA = new Thread(new Runnable() { @Override public void run() { // 线程A中发送数据 String data = "hello code 9527"; System.out.println("send data, run in thread : " + Thread.currentThread().getName() + ", data = " + data); // 通过DataHandler将数据拷贝到线程B中处理 mHandler.sendData(data); } }, "threadA"); threadA.start(); } }
运行结果:
send data, run in thread : threadA, data = hello code 9527
process data, run in thread : ThreadB, data = hello code 9527
从结果可以看出数据“hello code 9527”在线程A中被DataHandler拷贝出来,副本存放到DataHandler中,然后通过线程B中进行处理。这样就实现了数据在线程间的切换。实现切换的“灵魂操作”便是“数据拷贝”和“目标线程对拷贝副本的轮询”。实现原理是不是很简单?其实Android的Handler机制也是基于这种原理实现的,有兴趣的同学可以深入分析一下Handler源码。