一、进程
每个独立执行的任务是一个进程。
操作系统会划分多个时间片,每个时间片内将CPU分配给某个任务,时间片结束后,CPU将自动回收,再分配给下一个任务。由于CPU时间片都是纳秒和微妙级别,所以从外部看所有任务都在同时运行,但实际在同一个CPU上的任务都是串行执行的,这些任务都是时断时续的执行的。如果是多核,多个进程任务可以并行,单核的话多个进程任务只能串行。
多进程的优点:
1)可以同时运行多个任务
2)进程因IO阻塞的时候,可以让出CPU来执行其他的进程,提高CPU利用率
3)当系统有多个CPU时,可以为多个程序同时服务
多进程的缺点:
1)太笨重,不好管理。进程占用资源多,一台计算机能同时打开的应用程序是有限的。
2)进程的内容比较多,上下文切换成本高。
3)进程间地址空间隔离,通信成本高
二、多线程
由于进程上下文切换成本高、进程间通信成本高等问题,操作系统后来提出了多线程。把进程当做线程的资源容器,其中可以包含多个线程。线程间共享进程地址空间的代码、数据等,每个线程可以运行进程的一个子任务,线程可以被CPU独立调度。
CPU在同一个进程的多个线程间调度时,此时CPU还是保留在本程序中,这样提高了本进程所获得CPU的时间和利用率。
三、多进程 vs 多线程
1)线程之间可以共享数据;进程间共享数据成本高,通常只能通过共享内存或第三方存储进程如缓存或数据库等来共享数据。
2)线程间通信更加高效,它们都属于同一个进程
3)线程更加轻量级,容易切换
四、代码示例
运行如下代码两次,可以得到两个正在运行的JAVA进程。每个JAVA虚拟机是一个进程,其中的main函数等都是该虚拟机中的线程。
public class ProcessTest1 {
public static void main(String[] args) {
while (true) {
System.out.println("main thread is running " + (Math.random() * 100));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
下面程序中有一个main主线程,在main主线程中启动子线程Thread1.
1) new Thread1().start()方法将调用Thread1中的run方法,java虚拟机会启动一个线程来执行run方法。
2)主线程执行结束后,如果子线程还没有结束,则整个java程序不会结束。
public class ThreadTest1 {
public static void main(String[] args) throws InterruptedException {
new Thread1().start();
for(int i=0; i<10; i++) {
System.out.println("main thread is running ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
class Thread1 extends Thread {
public void run() {
for(int i=0; i<100000; i++) {
System.out.println("sub thread is running " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}