关于并发

区别与并行

感觉了解其区分,描述起来好难

他人的回答:

并发(Concurrency)是说进程B的开始时间是在进程A的开始时间与结束时间之间,我们就说A和B是并发的。

并行(Parallel Execution)是并发的真子集,指同一时间两个进程运行在不同的机器上或者同一个机器不同的核心上。

自己的话

并行是同一个时刻有多个任务被执行,至少得有两个CPU。

并发不要求同一个刻被运行,两个任务可以交替执行,或是同时运行,即并发包括了并行的情况。

工作中理解到并发

在Android中什么时候有多个任务并发运行呢?

多个任务并发运行,即可以理解为多个线程的情况。容易想到的是JVM中存在一个用于垃圾回收守护线程和主线程, 守护线程一直在监控着资源的使用情况,

进行耗时操作,比如网络请求、解析xml文件,创建一个子线程来处理。

子线程处理完后,如何将结果通知给主线程呢?

比如 Main 启动一个 A线程执行任务,那么计算完如何通知A线程呢?

想到的是创建一个Callback,创建任务传递A线程,那么在A线程计算得到结果后,调用callback?

若是在A线程中直接调用callback,那么该方法实在A线程中运行的,而我们想要该callback在 Main线程中执行呢?

想到这,此刻我有点惊讶我没有认真过这个问题~

我们假设一种简单情况,Main线程在启动A线程后,阻塞等待,等待A线程返回结果后再执行后续的处理, 那么可以使用 join()方法等待A线程 计算完成,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义一个公共变量,在A线程中修改,在主线程中展示,这里使用volatile使其修改对主线程可见
// 使用数组达到传址的效果
static int[] result = new int[]{-1};

public static void main(String[] args) throws InterruptedException {
Thread tA = new Thread(() -> {
result[0] = 100;
System.out.println("a:" + result[0]);
});

tA.start();

// 主线程等待a线程执行完
tA.join();

System.out.println("main:" + result[0]);
}

看了 join() ,其实现还是用了 wait/notify机制,直接使用wait/notify带来实现上述需求

obj.wait() 将该线程进入等待状态,知道其它线程调用obj的notify或被当前线程被中断
其本质是将本线程加入到obj的对象头中的等待集合中,并且本线程不再作为该对象的owner of the object’s monitor,
本线程不再拥有该对象的拥有权,注意是拥有该对象的所有权才能调用该方法的

obj.notify(),也是得到了该对象的所有权后才能调用notify(),故需要先获取锁再操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static int[] result = new int[]{-1};

// 使用一个对象作为锁
static final Object lock = new Object();


public static void main(String[] args) throws InterruptedException {

Thread tA = new Thread(() -> {
result[0] = 100;
System.out.println("a:" + result[0]);
synchronized (lock) { // 获取到锁
// 唤醒其他等待在该lock的一个线程
// 注意只是唤醒,其他线程还是等到本线程释放锁才能获取继续运行
lock.notify();
// 假设这里 sleep(3000),线程A还是会因为持有该锁,故,主线程得等到sync结束后才能继续运行
}
});

tA.start();
synchronized (lock) {
lock.wait();
}
System.out.println("main:" + result[0]);
}

以上,主线程阻塞运行,等待子线程结束后才继续运行,而,若是想再开启子任务后,想要主线程继续运行呢?

这个样的需求,其实就是Handle处理的场景,那我们不依赖Android如何实现呢?

思路

维护一个任务队列 queue,主线程开启一个死循环,不断取出队列中的任务来执行;
当我们想在主线程开启一个子线程来计算时,