进程与线程
- [1. 线程与进程](#1. 线程与进程)
-
- [1.1 概念](#1.1 概念)
- [1.2 区别与联系](#1.2 区别与联系)
- [2. 线程的5种状态和切换](#2. 线程的5种状态和切换)
-
- [2.1 简单介绍](#2.1 简单介绍)
- [2.2 状态切换](#2.2 状态切换)
-
- [2.2.1 重点情况](#2.2.1 重点情况)
- [3. 线程中常见的方法](#3. 线程中常见的方法)
- [4. 线程池](#4. 线程池)
1. 线程与进程
1.1 概念
进程:资源分配的基本单元,如QQ音乐
线程:资源调度的基本单元,如QQ音乐中的播放功能
1.2 区别与联系
①联系:
线程包含在进程里面,多个线程共享一个进程的内存空间;
进程之间是相互独立的,所以进程之间想要互相通信就得借助一些手段才可以;
②区别: 回答点------>地址空间、开销、并发性、内存、健壮性
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
地址空间:
- 进程之间各自独立,而多个线程之间是共享进程的地址空间;
- 线程有自己堆栈和局部变量;
开销:
- 进程的上下文切换时间开销消耗资源大,效率差;
- 线程由于共享一个地址空间,所以线程之间的切换非常快;
并发性:
- 进程的并发性低;
- 线程的并发性高;
内存:
- 系统在运行的时候会为每个进程分配不同的内存空间;
- 而对线程而言,除了 CPU 外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源;
健壮性:
- 一个进程崩溃后,在保护模式下不会对其他进程产生影响;
- 但是一个线程崩溃整个进程都会死掉。所以多进程要比多线程健壮;
其他:
- 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口
- 但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制;
2. 线程的5种状态和切换
线程的生命周期一共分为五个部分,分别是:新建,就绪,运行,阻塞,死亡
2.1 简单介绍
- 新建状态(New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()
- 就绪状态(Runnable): 此时线程正在就绪队列中排队等候得到CPU资源;(线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。)处于就绪状态的线程,随时可能被CPU调度执行。
- 运行状态(Running): 线程获得CPU资源正在执行,此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。需要注意的是,线程只能从就绪状态进入到运行状态。
- 阻塞状态 (Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程
重新进入就绪状态
,才有机会转到运行状态
。阻塞的情况分三种:线程阻塞态的具体分类
- (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成;
- (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
- (03) 其他阻塞 -- 通过调用线程的
sleep()
或join()
或发出了I/O
请求时,线程会进入到阻塞状态
;
当sleep()状态超时 、join()等待线程终止或者超时 、或者I/O处理完毕时 ,线程重新转入就绪状态
。- 死亡状态 (Dead): 当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
- 自然终止:正常运行run()方法后终止
- 异常终止:调用stop()方法让一个线程终止运行,该线程结束生命周期。
2.2 状态切换
注意:线程只能从就绪态
到运行态
2.2.1 重点情况
①运行------>阻塞
- 调用wait()方法,等待某事件发生(等待阻塞);
- 获取synchronized锁失败,(被其他线程正在使用)(同步阻塞);
- 发生I/O请求(等待用户输入)、调用sleep()或join()方法(其他阻塞)
①阻塞------>就绪
- sleep()、join()等待线程终止或者超时;
- I/O处理完毕时,线程重新转入就绪状态。
3. 线程中常见的方法
请大家看这篇博客:线程中常见的方法
4. 线程池
-
概念:一种多线程的处理形式,管理多个线程;
-
主要思想:在进程开始时创建一定数量的线程,并加到池中以等待工作。当服务器收到请求时,它会唤醒池内的一个线程(如果有可用线程),并将需要服务的请求传递给它。一旦线程完成了服务,它会返回到池中再等待工作。如果池内没有可用线程,那么服务器会等待,直到有空线程为止。
-
目的 :减少资源的消耗,提高对资源的利用率;
解释
:java线程的创建非常昂贵,需要JVM和OS(操作系统)互相配合完成大量的工作。而java高并发频繁的创建和销毁线程的操作是非常低效的,如何降低java线程的创建成本,就必须要使用到线程池。
-
使用线程池的优点:
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
-
线程池的七个参数:
corePoolSize
:核心线程数,线程池正常情况下保持的线程数,大户人家"长工"的数量maximumPoolSize
:最大线程数,当线程池繁忙时最多可以拥有的线程数,大户人家"长工"+"短工"的总数量。keepAliveTime
:空闲线程存活时间,没有活之后"短工"可以生存的最大时间。TimeUnit
:时间单位,配合参数keepAliveTime
一起使用,用于描述参数keepAliveTime
的时间单位。BlockingQueue
:线程池的任务队列,用于保存线程池待执行任务的容器。ThreadFactory
:线程工厂,用于创建线程池中线程的工厂方法,通过它可以设置线程的命名规则、优先级和线程类型。RejectedExecutionHandler
:拒绝策略,当任务量超过线程池可以保存的最大任务数时,执行的策略。