并发与分布式编程(Concurrent and Distributed Programming)
1.并发(Concurrency)
注意并发并不等于平行(Parallel),下面的图片就形象的解释了这一概念:
在现代编程中,并发性是必不可少的:
- 多用户并发请求服务
- App在手机端与云端都有计算
- GUI的前端用户操作和后台的计算
并发编程主要有两种模式:
- 共享内存:在内存中读写共享数据。
eg:两个处理器共享内存、同一台机器上的两个程序共享文件系统、同一个java程序内的两个线程共享Java对象等。 - 消息传递:通过channel交换信息。
eg:网络上两台计算机通过网络连接通讯、浏览器与web服务器,A请求页面,B发送页面数据给A、即时通讯软件的客户端和服务器、同一台计算机上的两个程序,通过管道连接进行通讯。
2. 进程与线程(processes and Threads)
进程(process):
进程拥有整台计算机的资源。但是多进程之间不共享内存,进程之间需要通过消息传递进行协作!
一般来说,进程==程序==应用。不过并不绝对,有的应用可能包含多个进程。操作系统支持IPC机制(pipe/socket)支持进程间通信。(不仅是本机的多个进程之间通信,也可以是不同机器的多个进程之间)
JVM通常运行单一进程,但也可以创建新的进程。
线程(Thread):
如果把进程比作为虚拟机,那么线程就可以看做虚拟CPU。线程之间程序共享、资源共享,都隶属于进程。
不过虽然线程之间共享内存,不过很难获取线程的私有的内存空间(栈),所以可以通过创建消息队列在线程之间进行消息传递。
单一线程与多线程对比:
最上面一层为共享层:包括代码、数据和文件系统。然而对于寄存器和栈各线程之间并不共享!
每个应该至少有一个线程,不过线程可以创建其他线程。
创建线程的方法主要分为两种:
- 从Thread类派生子类(附带两种启动线程的方式):
- 从Runnable接口构造Thread对象:
其实都差不多,不过对于比较简单的线程我都喜欢这么写,开个匿名类:
public static void main(String[] args) {
new Thread() {
public void run() {
//你的方法
}
}.start();
}
另外……和之前说的那个cloneable接口一样,千万别把这个Runnable接口看的多么高大上,虽然不像前面那个那么萌,不过也就一个方法而已,下附JDK源码:
public interface Runnable {
public abstract void run();
}
不过千万要记得启动线程不是要调用run方法!而是调用start方法!
3.交错与竞争(Interleaving and Race Condition)
时间分片:
虽然有多线程,但只有一个核,所以每个时刻只能执行一个线程。所以通过时间分片在多个进程/线程之间共享处理器。而且仅仅是多核CPU,进程/线程的数目也往往大于核的数目。
时间分片图解:
其实嘛……时间分片就是指执行线程的时间调度,就是叫的抽象了点,说白了就是我一次只能执行一个线程,现在有好多线程,所以需要一个方案,时间分片就是这个方案。这样讲会不会好理解一点呢?
值得说的是时间分片是由操作系统