进程和线程是什么?
计算机上的所有操作都是由cpu来执行的,cpu将要执行的操作分为一个个的任务,这些任务我们就可以理解为进程,而这些任务又分为一些细粒度更小的子任务,这些子任务就称作线程
cpu轮流执行任务的,每一个任务需要经过以下三个阶段:
- 加载上下文
- 执行
- 保存上下文
也就是说,每一个进程从加载、执行,到切换下一个进程执行,都会经历同样的一个过程,我们的cpu就是在无时无刻地进行这样的进程切换操作
而我们又可以把进程分为一些细粒度更小的线程,这些线程之间也可以来回的切换,就像进程一样,但是却不需要加载和保存上下文的操作,因为这些线程都是共享上下文的
进程与线程的区别
- 性质不同:进程是资源分配的基本单位,线程是cpu执行运算和调度的基本单位
- 归属不同:一个操作系统中可以有很多进程,一个进程可以有很多线程
- 开销不同:进程创建、销毁和切换的开销都要远大于线程
- 拥有资源不同:每个进程都拥有自己的内存和资源,一个进程中的线程会共享这些内存和资源
- 通信方式不同:进程之间可以通过管道、消息队列、共享内存、信号量,以及Socket等机制实现通信,线程之间主要通过共享变量及其变种形式实现通信
- 控制和影响能力不同:子进程无法控制父进程,一个进程发生异常时一般不会影响其他进程;子线程可以控制父线程,如果主线程发生异常,会影响其所在进程和其余线程
- 扩展能力不同:多进程可以方便地扩展到多机分布式系统上,多线程想要扩展到多台机器上就很困难
- cpu利用率不同:进程的cpu利用率低,因为需要额外的上下文切换开销;线程的cpu利用率高,因为切换简单
- 可靠性不同:进程的可靠性要高于线程
线程是系统调度的最小单元,一个进程可以包含多个线程,作为任务的真正运作者,有自己的栈(Stack)、寄存器(Register)、本地存储(Thread Local)等,但是会和进程内其他线程共享文件描述符、虚拟地址空间等。
一个线程两次调用start()发放会出现什么情况
- java线程不允许启动两次,第二次调用必报IIegalThreadStateException,这是一种运行时异常,多次调用start被认为是编译错误
- 生命周期
-
新建 :表示线程被创建后还没有真正启用的状态,是Java内部状态
-
就绪: 标识该线程已经在JVM中执行,当然由于执行需要计算资源,等待系统分配CPU片段,在就绪队列中排序
-
running Java API的角度,并不能表示出来
-
阻塞 :标识线程在等待Monitor lock。比如: synchronized 去获取某个锁,但是其他线程已经独占了,那么当前线程就会处于阻塞状态。
-
等待 :表述正在等待其他线程采取某些操作。生产者消费者,发现条件尚未满足,就让当前消费者等待,另外生产者线程去准备任务数据,然后通过notify等动作,通知消费线程可以继续工作了。 hread.join() 也会令线程进入等待状态
-
计时等待: 其进入条件和等待状态类似,但是调用的是存在超时条件的方法,比如 wait 或 join 等方法的指定超时版本,
-
终止:结束
-