进程:资源的分配和调度的一个独立单元
线程:CPU调度的基本单元,存在于进程中,比如微信要接受消息,发送消息,这些子任务就是线程。
联系:同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包括一个线程。
Http请求的线程形式:
http请求,到业务处理,再到响应的过程,是在一个线程里面的。一个线程由一个方法启动,但是一个线程里面可以有多个线程,并不是每个方法都是一个线程,只有当启动线程结束时,该线程才终止。 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。tomcat会维护一个线程池,每一个http请求,会从线程池中取出一个空闲线程。默认初始化75个线程,可以进行修改。
java线程调度:
线程调度是指系统为线程分配处理器使用权的过程,主要调度方式分两种,分别是协同式线程调度和抢占式线程调度。
协同式线程调度:线程执行时间由线程本身来控制,线程把自己的工作执行完之后,要主动通知系统切换到另外一个线程上。最大好处是实现简单,且切换操作对线程自己是可知的,没啥线程同步问题。坏处是线程执行时间不可控制,如果一个线程有问题,可能一直阻塞在那里。
抢占式调度:每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定(Java中,Thread.yield()可以让出执行时间,但无法获取执行时间)。线程执行时间系统可控,也不会有一个线程导致整个进程阻塞。
Java线程调度就是抢占式调度。
希望系统能给某些线程多分配一些时间,给一些线程少分配一些时间,可以通过设置线程优先级来完成。Java语言一共10个级别的线程优先级,在两线程同时处于ready状态时,优先级越高的线程越容易被系统选择执行。但优先级并不是很靠谱,因为Java线程是通过映射到系统的原生线程上来实现的,所以线程调度最终还是取决于操作系统。
补充:
1. 中央处理器,是一块超大规模的集成电路,是一台计算机的运算核心和控制核心。 它的工作,主要是解释计算机中的指令,和处理计算机软件中的数
据。它在计算机中起着最重要的作用,构成了系统的控制中心,对各个应用程序进行统一协调和控制。
2. java线程只能抢占cpu的执行权,但是无法控制执行时间,即当一个线程在执行某一方式时,即使该方法没有执行完,也即该线程没有执行完,但是系统分配给该线程的执行时间已经到了,这时该线程独立的程序计数器,会存储虚拟机字节码指令地址,当该线程重新获取cpu执行权时,将不会重新开始执行线程的所有方法,而是会从该线程中的程序计数器中获取字节码指定地址,然后从这里开始继续执行。
3. 线程在执行I/O时,只有在开始或者结束时需要cpu做一定处理,在执行I/O程序期间,是不需要cpu干预的,换言在,即程序在进行I/O操作时,JVM会将该线程设置为阻塞状态,当I/O处理完毕时,线程会重新转入就绪状态。
单核cpu和多核cpu:
- 都是一个cpu,不同的是每个cpu上的核心数
- 多核cpu是多个单核cpu的替代方案,多核cpu减小了体积,同时也减少了功耗
- 一个核心只能同时执行一个线程
- 所谓的4核8线程,4核指的是物理核心。通过超线程技术,用一个物理核模拟两个虚拟核,每个核两个线程,总数为8线程。在操作系统看来是8个
核,但是实际上是4个物理核。通过超线程技术可以实现单个物理核实现线程级别的并行计算,但是比不上性能两个物理核。
线程切换:
- cpu给线程分配时间片(也就是分配给线程的时间),执行完时间片后会切换都另一个线程。
- 切换之前会保存线程的状态,下次时间片再给这个线程时才能知道当前状态。
- 从保存线程A的状态再到切换到线程B时,重新加载线程B的状态的这个过程就叫上下文切换。
- 而上下切换时会消耗大量的cpu时间。
线程开销:
- 上下文切换消耗
- 线程创建和消亡的开销
- 线程需要保存维持线程本地栈,会消耗内存
多线程的优点:
1. 使用线程可以把占据时间长的程序中的任务放到后台去处理
2. 用户界面更加吸引人,这样比如用户点击了一个按钮去触发某件事件的处
理,可以弹出一个进度条来显示处理的进度
3. 程序的运行效率可能会提高
4. 在一些等待的任务实现上如用户输入,文件读取和网络收发数据等,线程就
比较有用了.
多线程的缺点:
1. 如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换.
2. 更多的线程需要更多的内存空间
3. 线程中止需要考虑对程序运行的影响.
4. 通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生
线程的生命周期:
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方
法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用
权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时
停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分
三种:
(一)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待中。
(二)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程
占用,则JVM会把该线程放入锁池中。
(三)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求
时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程
终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
resume(),suspend(),stop()方法已经过时了,舍弃不用