目录
进程
线程
多线程
执行
并发
并行
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。进程一般由程序、数据集合、进程控制块三个部分组成。
程序:用于描述进程要完成的功能,是控制进程执行的指令集。
数据集合:程序在执行时,需要的数据和工作区。
进程控制块:包含进程的描述信息和控制信息,是进程存在的唯一标志。
线程是操作系统能够进行运算调度的最小单位。线程被包含在进程中,是进程中的实际运作单位。进程是程序的基本执行实体,可以理解为是线程的容器。
如果把进程看成是一家餐厅,那么线程就是员工。餐厅要运营,必须要让员工工作。餐厅只是提供资源和场所,真正对客人进行服务的是员工。
例如,我们运行以下代码。
运行:餐厅建好了,招了一个员工myThread,员工的工作就是输出打印。
结束:餐厅倒闭了,释放资源。
public class Demo {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.setName("线程员工");
myThread.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println(getName() + "打印了:hello world!");
}
}
结果:
线程员工打印了:hello world!
既然要开一家餐厅,只有一个员工怎么行。员工又分前台、厨师、服务员,也就是说员工们可以同时做不同的事,各施其职。当然多个员工做同一件事也行,比如服务员都是来服务客人的,干的都是服务客人这件事。但是服务员服务客人,在每个服务员之间是相互独立的,你服务你的客人,我服务我的客人。但话又说回来,大家都是同一家餐厅的,也就意味着资源是共享的。
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务。每个线程都有自己的专有寄存器(如栈指针、程序计数器),但代码区是共享的,即不同的线程可以执行同样的方法。多线程技术允许单个程序创建多个并行执行的线程来完成各自的任务,从而提高整体的处理性能。
多线程是一种机制,允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程与进程相似,但线程更为轻量级,并且专注于执行单一的任务。多线程是多任务的特殊形式,它能够提高系统的效率,特别是在需要同时完成多项任务的情况下。
说白了就是要餐厅员工们好好配合,各施其职。
如下代码,线程员工1和线程员工2的工作都是输出打印,各自进行。可能是线程员工1先完成输出打印,也有可能是线程员工2。因为两个线程是相对独立的,结果就是都完成了工作,但是完成的顺序可能会不一样。
public class Demo {
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.setName("线程员工1");
myThread2.setName("线程员工2");
myThread1.start();
myThread2.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println(getName() + "打印了:hello world!");
}
}
结果:
线程员工1打印了:hello world!
线程员工2打印了:hello world!
或
线程员工2打印了:hello world!
线程员工1打印了:hello world!
以下代码执行的结果是(使用多线程):
耗时:1ms
线程员工打印了耗时:503ms
public class Demo {
public static void main(String[] args) {
long begin = System.currentTimeMillis();
MyThread myThread1 = new MyThread();
myThread1.setName("线程员工");
myThread1.start();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - begin) + "ms");
}
}
class MyThread extends Thread {
@Override
public void run() {
long begin = System.currentTimeMillis();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println(getName() + "打印了耗时:" + (end - begin) + "ms");
}
}
以下代码执行的结果是(不使用多线程):
线程员工打印了耗时:503ms
耗时:507ms
public class Demo {
public static void main(String[] args) {
long begin1 = System.currentTimeMillis();
/*MyThread myThread1 = new MyThread();
myThread1.setName("线程员工");
myThread1.start();*/
long begin = System.currentTimeMillis();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println("线程员工" + "打印了耗时:" + (end - begin) + "ms");
long end1 = System.currentTimeMillis();
System.out.println("耗时:" + (end1 - begin1) + "ms");
}
}
class MyThread extends Thread {
@Override
public void run() {
long begin = System.currentTimeMillis();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long end = System.currentTimeMillis();
System.out.println(getName() + "打印了耗时:" + (end - begin) + "ms");
}
}
两者之间的差异很大,使用多线程不需要等待任务完成,不使用多线程需要。
那如果我们有多个任务,不用多线程,任务一个一个地执行,花费的时间很多。使用多线程的话,效率会变高。
多线程是并发执行的
按最简单、最基本的程度理解,并发是两个或多个同时独立进行的活动。并发现象遍布日常生活,我们可以边走路边说话,左右手同时做出不一样的动作,诸如此类。
就多线程代码而言,并发与并行的含义很大程度上相互重叠。并发和并行的差别甚小,主要是着眼点和使用意图不同。两个术语都是指使用可调配的硬件资源同时运行多个任务,但并行更强调性能。当人们谈及并行时,主要关心的是利用可调配的硬件资源提升大规模数据处理的性能;当谈及并发时,主要关心的是分离关注点或响应能力。
分离关注点:归类相关代码,隔离无关代码,使程序更易于理解和测试,因此所含缺陷很可能更少。
为分离关注点而并发,为提升性能而并行。