概念


进程:进行中的应用程序。属于CPU分配资源的最小单

线程:线程包含在进程之中的,一个进程至少包含一个线程,线程是CPU执行的最小单位

线程是CPU进行运算调度的最小单位

同步:按照一定次序,有序执行,先来后到

异步:同时执行,互不影响

并行:多个CPU同时执行多个任务

并发:一个CPU执行多个任务,不同时

多线程和主线程

单线程:只有一个线程,代码顺序执行,操作具有原子性,但容易出现代码阻塞(页面假死)。

单任务进程及单线程效率是最高的,因为CPU没有任何进程及线程的切换开销。

多线程:有多个线程,线程间独立运行,能有效地避免代码阻塞,并且提高程序的运行性能

如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”

多线程的出现主要为了解决IO设备的读写速度往往比CPU的处理速度慢造成的单线程程序运行阻塞问题

单核CPU下,多个线程交替占用CPU资源,而非真正的并行执行

多线程好处:

充分利用CPU的资源、简化编程模型、带来良好的用户体验

main方法底层是由main线程来负责执行的,main线程也叫主线程

线程的五种状态

创建===》就绪===》运行===》阻塞===》死亡

线程的生命周期即上述五种状态

影响生命周期的方法

sleep     wait     notify     yeild     join     start

线程的创建方式

1.继承Thread类,重写run()方法,使用start方法开启线程

2.实现Runnable接口,创建Thread对象,使用Thread对象调用start方法开启线程

3.实现Callable接口

1和2创建方式的问题:     1.无法获取子线程的返回值。          2.run方法不可以抛出异常

Runnable接口和Callable接口的区别

两者都能用来创建线程,但是实现Callable接口的线程能返回执行结果,而实现Runnable接口的线程不能返回结果;而且Callable通常需要和Future结合使用,用于获取异步计算结果。


4.线程池创建

实现线程安全的方法

线程安全:多个线程操作同一资源,可能会引发资源重复的问题

条件:1.多线程         2.操作同一资源                  3.对资源更改    

积极避免这种现象

实现:

1.通过同步代码块解决线程安全问题

2.通过同步方法来实现线程安全

3.使用lock锁实现线程安全

生产者和消费者模型

实现线程的动态平衡

wait和notify

会写生产者消费者模型代码

线程池

为什么要使用线程池

线程池就是一个管理线程的一种手段

作用:就是重用创建的线程,减少创建线程销毁线程造成资源浪费,形成资源隔离,提供了定时任务,周期执行任务,多个线程同时执行等功能。

springboot中维护线程池

1.配置线程池类,设置线程池参数。    ------    说这个就行

2.配置启动类

3.使用线程池

几种常见的线程池

FixedThreadPool:是一种有固定的长度的线程池,线程池里边没有非核心线程,当线程池中的线程没有被调用,线程会返回线程池中等待被调用。

CachedThreadPool:没有核心线程,只有非核心线程,需要的时候就创建,不需要的时候不会回到线程池中,会被回收。

ScheduleThreadPool:这种线程池是可以设置固定长度的核心线程,也有无限制的非核心线程,一般用来执行定时任务,以及周期性任务,核心线程不会被回收,非核心线程类会被回收。

SingleThreadPool:这个线程池只有一条线程来执行任务,不能设置固定长度。

为什么不建议使用JDK中自带的线程池

jdk自带的线程池的任务队列是无限大的,容易产生内存溢出

线程池的七大参数

核心线程数、最大线程数、空闲线程等待时间、空闲线程等待时间单位、工作队列、线程工厂、拒绝策略

线程池的五大状态

1、RUNNING        ---        running

(1)状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。

(2)状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,

并且线程池中的任务数为0!

2、SHUTDOWN    ---        shutdown

(1)状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。

(2)状态切换:调用线程池的shutdown(0接口时,线程池由RUNNING->SHUTDOWN。

3、STOP            ---        stop

(1)状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

(2)状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNINGor SHUTDOWN)->STOP。

4、TIDYING        ---        tidying

(1)状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

(2)状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由SHUTDOWN ->TIDYING.

当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP->TIDYING。

5、TERMINATED    ---        terminated

(1)状态说明:线程池彻底终止,就变成TERMINATED状态。

(2)状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由TIDYING->TERMINATED。

线程池的4种拒绝策略

拒绝策略就是当所请求的线程数量大于线程池的核心线程数的时候,先把线程任务放到任务队列里边,如果阻塞队列满后,还有线程任务直到线程池的最大线程数后,才会开启拒绝策略。

AbortPolicy策略:            该策略会直接抛出异常;丢弃任务并抛出异常

CallerRunsPolicy策略:        只要线程池未关闭,该策略直接在调用者线程中运行当前被放弃任务;

DiscardOledestPolicy策略:    丢弃最老的一个请求,也就是丢弃一个即将被执行的任务,并尝试再提交当前任务;

DiscardPolicy策略:        该策略丢弃无法处理的任务,不做任何处理

解决线程安全:锁

synchronized:互斥锁,同步锁

用法有三种:1.修饰代码块           2.修饰实例方法           3.修饰静态方法

锁的粒度,从小到大,实现同步的原理基于JVM

作用:1.原子性                 2.可见性                  3.有序性

原理:JVM中对象监视器(ObjectMonitor),获取锁-进入(Monitor Enter),离开锁(Monitor Exit),进入获取一次,会进行计数+1,离开1次,会-1.等为0时,才会释放锁

可重入锁:同一个线程,对于同一个锁,可以反复进入多次

加锁修改对象头

对象堆内存存储的内容


  •          对象头:锁的类型,GC,年龄,偏向锁等
  •            对象属性
  •              对齐字节


Lock

基于JDK实现 接口 实现类:ReentrantLock

原理:CAS+自旋 双向链表 计数值

公平锁:按次序,先来后到,非公平:竞争

CAS(比较并替换-乐观锁)和ABA

                 线程安全的情况下,当前线程加入到链表末尾

                 自旋 (AQS内部获取锁,自旋+CAS)

1.ABA:期望值为A,中间其他线程把期望值改成了B或者其他,最后又有线程改成了A,解决方案,在CAS的时候添加版本号

2.自旋消耗:如果自旋不成功,就会一直霸占CPU.必须有超时机制或者次数限制,特殊情况结束自旋。ConCurrentHashMap(1.8)

3.CAS只能单变量

AQS:AbstractQueuedSynchronizer

          实现公平和非公平锁,记录获取当前锁的线程对象

          lock:加锁--自旋+CAS

          addWaiter:添加到等待链表中

            unlock:释放锁 tryRelease 计数值-1

volatile:关键字

指令关键字,修饰的内容不会被编译器优化而省略

原子性(单次操作),可见性(线程间实时可见) ,有序性(禁止指令重排)

AtomicInteger

ThreadLocal

线程本地变量(线程副本),每个线程都有自己的变量,线程安全

原理:类似Map集合,Key:线程对象,Value:变量,Thread.currentThread()获取key,ThreadLocalMap Entry

内存泄漏:ThreadLocal内部使用的是弱引用+弱引用队列

           弱引用:GC运行回收对象,所以避免内存泄漏:用完之后调用remove