(本文由言念小文原创,转载请注明出处)

一  前言
有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源码。

Java线程切换(一)的更多相关文章

  1. 基于 JVMTI 实现 Java 线程的监控(转)

    随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...

  2. Java线程状态切换以及核心方法

    1.Java线程状态 1.1 线程主要状态 ①初始(NEW):新创建了一个线程对象,但还没有调用start()方法.②运行(RUNNABLE):Java线程中将就绪(ready)和运行中(runnin ...

  3. java中线程切换的开销

    思路: 开三个线程A,B,C 线程A不断的调用LockSupport.park()阻塞自己,一旦发现自己被唤醒,调用Thread.interrupted()清除interrupt标记位,同时增加自增计 ...

  4. Java线程生命周期与状态切换

    前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...

  5. Java线程状态及切换

    Java线程状态及切换 一.什么是Java线程状态 在Java程序中,用于描述Java线程的六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动. 运行(RUNNABLE):当前线程,处于竞争 ...

  6. 透彻讲解,Java线程的6种状态及切换

    Java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法.2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running) ...

  7. Java线程的6种状态及切换

    Java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法.2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running) ...

  8. 并发编程——Java线程的6种状态及切换

    前言 本次主要分享一下Java线程的六种状态及其转换. 如果对于线程的创建方式不太了解,推荐观看并发编程--认识java里的线程 线程的状态及其转换 操作系统线程的五种状态 新建(NEW) 就绪(RU ...

  9. Java线程的概念

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

随机推荐

  1. SpringBoot起飞系列-Web开发(四)

    一.前言 从今天你开始我们就开始进行我们的web开发,之前的一篇用SpringBoot起飞系列-使用idea搭建环境(二)已经说明了我们如何进行开发,当然这是搭建起步,接下来我们就开始进行详细的开发, ...

  2. 一个有意思的js块作用域问题

    1.问题 首先把问题放出来,昨天看了一个掘友发的一个问题,然后跟我同事一起研究了一下,没找出来是为什么,然后我回来一直在想为什么,然后各种找资料研究,从各个方面找为什么,比如js上下文,作用域,js垃 ...

  3. Spring Environment的加载

     这节介绍environment,默认环境变量的加载以及初始化.  之前在介绍spring启动过程讲到,第一步进行环境准备时就会初始化一个StandardEnvironment.下图为Environm ...

  4. invalid comparison: java.util.ArrayList and java.lang.String解决

    报错: Caused by: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause ...

  5. .Net Core 商城微服务项目系列(八):购物车

    最近加班有点多,一周五天,四天加班到11点+,心很累.原因是我当前在的这个组比较特殊,相当于业务的架构组,要为其它的开发组提供服务和监控.所以最近更新的也少,不过这个元旦三天假应该会更新三篇. 这篇是 ...

  6. 3. Git与TortoiseGit基本操作

    1. GitHub操作 本节先简单介绍 git 的使用与操作, 然后再介绍 TortoiseGit 的使用与操作. 先看看SVN的操作吧, 最常见的是 检出(Check out ...), 更新 (U ...

  7. Dedecms手机站三种不同建设方法和优劣分析

    dedecms简单易用功能强大,是国内使用最多的cms建站系统,百度站长平台专门推出了“织梦移动化指南”,由此可见dedecms的影响力.织梦也是站长使用和学习最早的cms建站系统,解放了我的双手,让 ...

  8. JZOJ10004 列车调度

    [JZOJ100041]列车调度 Description Input Output Sample Input Sample1: 3 1 2 3 Sample2: 9 1 3 2 4 8 6 9 5 7 ...

  9. 第10项:重写equals时请遵守通用约定

      重写equals方法看起来似乎很简单,但是有许多重写方式会导致错误,而且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每个实例都只能与它自身相等.如果满足了以 ...

  10. Vue-CLI项目路由案例汇总

    0901自我总结 Vue-CLI项目路由案例汇总 router.js import Vue from 'vue' import Router from 'vue-router' import Cour ...