Android并发编程 开篇

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!

前言

从本篇博文开始Android并发编程系列。由于笔者水平有限,如果博文之中有任何错误或者纰漏之处,还请不吝赐教。

Java线程

在Android SDK中并没有提供新颖的线程实现方案,使用的依旧是JDK中的线程。在Java中开启新线程有3中常见的方式

继承自Thread类,重写run()方法

public class ThreadA extends Thread { @Override public void run() { try { Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()); } } //测试的主线程 public class Main { public static void main(String[] args){ ThreadA threadA = new ThreadA(); threadA.setName("threadA"); threadA.start(); System.out.println("主线程"+Thread.currentThread().getName()); } }

实现Runnable接口,实现run()方法

public class ThreadB implements Runnable{ @Override public void run() { try { Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); } } //测试的主线程 public class Main { public static void main(String[] args){ ThreadB threadB = new ThreadB(); //注意这里启动的方式跟方式1不一样 Thread thread = new Thread(threadB); thread.setName("threadB"); thread.start(); System.out.println("主线程"+Thread.currentThread().getName()); } }

实现Callable接口,实现call()方法

public class ThreadC implements Callable<String> { @Override public String call() throws Exception { try { Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } return Thread.currentThread().getName(); } } public class Main { public static void main(String[] args){ ThreadC threadC = new ThreadC(); //FutureTask 后续会讲到,先知道有怎么个实现方式 FutureTask<String> feature = new FutureTask<>(threadC); //注意启动方式有点不一样; Thread thread1 = new Thread(feature); thread1.setName("threadC"); thread1.start(); //注意细细体会这个,只有主线程get了,主线程才会继续往下面执行 try { System.out.println(feature.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("主线程"+Thread.currentThread().getName()); } } JMM(Java 内存模型)

上面简单的介绍了3种开启线程的方式,接下来我们来看一下Java的内存模型,因为后续文章讲到的许多知识都需要这个作为基础。

主内存与工作内存

JMM规定JVM有主内存(Main Memory)和工作内存(Working Memory),主内存其实就是我们平常所说的Java堆内存,存放所有类实例变量等,这部分内存是多个线程共享的;工作内存里存放的则是线程从主内存拷贝过来的变量以及访问方法得到的临时变量,这部分内存为线程私有,其他的线程不能访问。

注:上面所说的拷贝并不是拷贝整个对象实例到工作内存,虚拟机可能拷贝对象引用或者对象字段,而不是整个对象。

主内存与工作内存的关系如下图所示

Android并发编程 开篇

主内存与工作内存间的交互操作

主内存与工作内存之间具体的交互协议,被定义了以下8种操作来完成,虚拟机实现时必须保证每一种操作都是原子的、不可再分的。

lock,锁定,所用于主内存变量,它把一个变量标识为一条线程独占的状态。

unlock,解锁,解锁后的变量才能被其他线程锁定。

read,读取,所用于主内存变量,它把一个主内存变量的值,读取到工作内存中。

load,载入,所用于工作内存变量,它把read读取的值,放到工作内存的变量副本中。

use,使用,作用于工作内存变量,它把工作内存变量的值传递给执行引擎,当JVM遇到一个变量读取指令就会执行这个操作。

assign,赋值,作用于工作内存变量,它把一个从执行引擎接收到的值赋值给工作内存变量。

store,存储,作用域工作内存变量,它把工作内存变量值传送到主内存中。

write,写入,作用于主内存变量,它把store从工作内存中得到的变量值写入到主内存变量中。

8种操作的实现规则:

不允许read和load、store和write操作之一单独出现,即不允许加载或同步工作到一半。

不允许一个线程丢弃它最近的assign操作,即变量在工作内存中改变了之后,必须吧改变化同步回主内存。

不允许一个线程无原因地(无assign操作)把数据从工作内存同步到主内存中。

一个新的变量只能在主内存中诞生。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppxgx.html