Java线程切换(一)
(本文由言念小文原创,转载请注明出处)
一 前言
有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线程切换(一)的更多相关文章
- 基于 JVMTI 实现 Java 线程的监控(转)
随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...
- Java线程状态切换以及核心方法
1.Java线程状态 1.1 线程主要状态 ①初始(NEW):新创建了一个线程对象,但还没有调用start()方法.②运行(RUNNABLE):Java线程中将就绪(ready)和运行中(runnin ...
- java中线程切换的开销
思路: 开三个线程A,B,C 线程A不断的调用LockSupport.park()阻塞自己,一旦发现自己被唤醒,调用Thread.interrupted()清除interrupt标记位,同时增加自增计 ...
- Java线程生命周期与状态切换
前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...
- Java线程状态及切换
Java线程状态及切换 一.什么是Java线程状态 在Java程序中,用于描述Java线程的六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动. 运行(RUNNABLE):当前线程,处于竞争 ...
- 透彻讲解,Java线程的6种状态及切换
Java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法.2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running) ...
- Java线程的6种状态及切换
Java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法.2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running) ...
- 并发编程——Java线程的6种状态及切换
前言 本次主要分享一下Java线程的六种状态及其转换. 如果对于线程的创建方式不太了解,推荐观看并发编程--认识java里的线程 线程的状态及其转换 操作系统线程的五种状态 新建(NEW) 就绪(RU ...
- Java线程的概念
1. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...
随机推荐
- opencv图像处理之常见滤波器
图像平滑 Smoothing, also called blurring, is a simple and frequently used image processing operation. 平滑 ...
- CDH集群的时间同步--简要配置要求
每个节点执行ntpstat 和 timedatectl 都显示同步并且时间相同,那么CDH才能正常使用.每次ntp服务同步到外部授时中心都要一段时间(5~10分钟),只有当NTP server(nod ...
- zookeeper特性与节点说明
一.zookeeper概要.背景及作用 zookeeper产生背景: 项目从单体到分布式转变之后,将会产生多个节点之间协同的问题.如: 每天的定时任务由谁哪个节点来执行? RPC调用时的服务发现? 如 ...
- 88.CSS---Grid 网格布局教程
grid 兼容性查看请点此处 最新Grid兼容 grid 布局就是给父元素(容器)添加display:grid,然后使子元素(项目)改变布局, 1 2 3 4 5 6 7 8 9 上面九个正方形的代码 ...
- Spring BeanDefinition的加载
前面提到AbstractRefreshableApplicationContext在刷新BeanFactory时,会调用loadBeanDefinitions方法以加载系统中Bean的定义,下面将讲 ...
- JS/jQuery点击某元素之外触发事件
JQuery // 第一步:点击任何地方都触发事件 $(document).click(function(){ alert("点击当前页面的任何地方都触发此点击事件:"); }); ...
- 【集群监控】Docker上部署Prometheus+Alertmanager+Grafana实现集群监控
Docker部署 下载 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.re ...
- 【产品】PM常用的流程图
一.流程图分类 UML有很多种,大体可以分类两类:行为型的图和结构型的图.平时工作中的流程图,只要能把事情清晰的表明,用何种流程图表现形式,其实都无所谓. 但是,作为一名产品经理,共有哪些种类的流程图 ...
- kotlin系列文章 --- 1.初识kotlin
简介 Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由Jetbrains设计开发,现在是Android官方开发语言,和Java具有互操作性,可以共存. 为什么选择kotlin? 简 ...
- redis主从配置 从而实现数据备份和读写分离
首先打开cmd,用cd找到你的redis文件夹,我的操作是 在你的第一个redis客户端文件夹配置文件中,搜索port,找到如下位置 端口号设置为6379(默认的.后面一个,两个或者多个客户端分别修改 ...