史上最全的多线程概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32258777/article/details/81089706

进程:资源的分配和调度的一个独立单元

线程: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()方法已经过时了,舍弃不用

猜你喜欢

转载自blog.csdn.net/qq_32258777/article/details/81089706
今日推荐