线程
线程的相关概念:
并行:指在同一时刻,有多条指令在多个处理器上同时执行。
并发:指在同一时刻,只能有一条指令执行,但多个进程指令之间被快速轮换执行,使得在宏观上具有多个线程同事执行的效果
进程:进程指正在运行的程序。确切的说,当一个程序进入内存运行,即变成了一个进程。进程是处于运行过程中的程序,并且具有一定独立功能
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,一个进程中可以有多个线程,这个应用程序也可以称为多线程程序
多线程:一个程序中有多个线程在同事执行,一个核心的CPU在福讴歌线程之间进行着随即切换动作,由于切换时间很短(毫秒,纳秒)导致我们感觉不出俩
线程的创建有三种方式
- 实现Runnable接口
- 继承Thread,重写run()方法
- 使用Callable和Future接口
创建线程的三种方式的对比
继承Thread类
优点:编写简单,如需访问当前线程,无需使用ThreadcurrentThread()方法,直接使用this即可获得当前线程
缺点:线程已经继承Thread类,所以不能再继续继承其他父类- 实现Runnable接口
优点:可以继承其他类,多个线程可以共享同一个Target
缺点:run()方法没有返回值,而且不能抛异常- 实现Callable接口
优点:call()方法可以有返回值,可以声明抛出异常
缺点:使用复杂
获取线程名称的两个方法:
* static Thread currentThread(): Thread类的静态方法,该方法返回对当前正在执行的线程对象的引用
* final String getName() :Thread类的示例方法,返回该线程的名称
线程池
线程池是指在初始化一个多线程应用程序的过程中创建的线程集合,然后在执行新的任务重用这些线程,线程池中的每个线程都有被分配一个任务,一旦任务完成,线程回到尺子中等待下一次的分配任务
使用线程池的好处
- 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗
- 提高响应速度:当任务到达时,任务可以不需要的等到线程创建就能立即执行
- 提高了线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控
线程池的实现原理
当一个新任务提交到线程池时,处理流程如下:
* 1、判断核心线程池里的线程是否都在执行任务,如果不是则创建一个新的工作线程处理任务,否则进入下一个流程
* 2、判断工作队列是否已满,如果未满则将新提交的任务存储在该工作队列中,否则进入下一个流程
* 3、判断线程池中的线程是否都处于工作状态,如果不是则创建一个新的工作线程来执行任务,否则交于饱和策略处理
线程比作员工,线程池比作一个团队,核心池比作团队中核心团队员工数,核心池外的比作外包员工
ThreadPoolExecutor构造函数的参数
- corePoolSize:核心线程池数量
- 在线程数少于核心数量时,有新任务进来就新建一个线程
- 等超出核心数量后,就不会新建线程了,空闲的线程就得去任务队列里取任务执行了
- maximumPoolSize:最大线程数量
- 包括核心线程池数量+核心以外的数量
- 如果任务队列满了,并且池中线程数小于最大线程数,会再创建新的线程执行任务
- keepAliveTime:核心池以外的线程存活时间,即没有任务的外包的存活时间
- 如果给线程池设置allowCoreThreadTimeOut(true),则核心线程在空闲时头上也会响起死亡的倒计时
- 如果任务是多而容易执行的,可以调大这个参数,那样线程就可以在存活的时间里有更大可能接受新任务
- workQueue:保存带执行任务的阻塞队列
- 不同的任务类型有不同的选择
- threadFactory:每个线程创建的地方
- 可以给线程设置优先级,命名
- Handler:饱和策略(大家都很忙,咋办呢?有四种策略)
- CallerRunsPolicy:只要线程池没关闭,就直接用调用者所在线程来运行任务
- AborPolicy:直接抛出RejectedExecutionException异常
- DiscardPolicy:把任务放生,不做了
- DiscardOldestPolicy:把队列里带最久的那个任务扔了,然后调用execute()
- 可以实现自己的RejectedExecutionHandler接口自定义策略
java中通过Executors提供了四种线程池
newCachedThreadPool(全部外包)
没有核心线程,非核心线程无上限,当提交任务速度大于处理任务速度时,每提交一个任务,就会创建一个线程,存活时间60s
newFixedThreadPool (不招外包,有固定数量的团队)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待,用于负载比较重的服务器,为了资源的合理利用,需要限制当前线程数量
newScheduledThreadPool(核心和外包都有)
创建一个订场线程池,支持定时及周期性任务执行
newSingleThreadExecutor(不招外包,只有一个核心成员的创业团队)
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
比较幸运的是:很多大神都有写过这方面的博客,这里推荐一篇https://blog.youkuaiyun.com/mine_song/article/details/70948223