一、程序、进程、线程的区别

程序:存储在磁盘上的静态代码,没有被执行的代码,通俗讲,程序是指令和数据的集合,执行程序实际上就是取出指令、计算数据的过程。
进程:程序放入内存中才可以执行,程序在内存中经CPU调度进行一次完整的动态执行过程则称为进程,进程是资源分配的单位,进程拥有共享的资源,如内存空间等,供其内部的线程分配共享,进程是不活动的,只是作为线程的容器,线程从里面自行分配取资源。

怎么理解进程是资源分配的最小单位?
为每一个进程划分具体固定的内存空间,以及相关其它资源,进程本身并不活动,实际真正在起作用的是内部的线程,比如进程划分了200M的内存空间供线程使用,线程会根据自身复杂程度去划分线程所用的内存空间、以及调用CPU的情况。拿Java执行过程为例,每个线程会独占一个栈内存,栈内存中存储了此线程执行过程中可能涉及到的方法内局部变量、操作数等。

线程:计算机调度的最小单位,是计算机执行的最小单位,是代码的一次执行过程,可以直接理解成一系列机器指令的集合,调度的最小单位是指CPU每次会调度线程,比如执行线程1的指令时,CPU可能会临时转换到线程2上,以执行线程2的指令。直观上理解在Java中,main方法是一个主线程,Thread()开启一个单独的线程。

单核CPU时,每次只能调度一个线程,当单核采用多个多线程的时候实际上并不会加快效率,因为是在多个线程之间不停的切换,与串行依次执行没有差别。
多核CPU时,多线程才会极快提高效率,因为每个核都会去调度线程,线程之间完全独立运行互不影响。
image.png

二、创建和运行线程

方法一,直接使用Thread

image.png

方法二,使用Runnable配合Thread

将【线程】和【任务】分开,Thread代表线程,Runnable是可运行的任务(线程要执行的代码)
此方法最合理且最常用
image.png

方法三,FutureTask配合Thread

FutureTask能够接受Callable类型的参数,用来处理有返回结果的情况
image.png

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
image.png

小技巧:Java8以后可以使用lambda精简代码

  1. Runnable task = ()->{
  2. //run方法内代码内容
  3. }
  4. //当Runnable接口内只有一个方法需要实现的时候,可以使用()->{}表示该接口一个实现类的对象,且{}里是唯一方法的实现细节

三、观察多个线程同时运行

线程是交替执行,无法判断线程间的执行顺序。
因为是CPU在调度线程,而且是一个cpu在单独执行线程还是一个cpu在轮换多个线程执行也不清楚,所以无法判断执行顺序。