线程状态
线程被创建并启动以后不是立刻就进入执行状态也不是一直处于执行状态
线程状态
线程状态 含义 NEW 一个尚未启动的线程的状态。也称之为初始状态、开始状态。线程刚被创建,但是并未 启动。还没调用start方法。MyThread t = new MyThread()只有线程象,没有线程特征。
RUNNABLE 当我们调用线程对象的start方法,那么此时线程对象进入了RUNNABLE状态。那么此时 才是真正的在JVM进程中创建了一个线程,线程一经启动并不是立即得到执行,线程的运行与否要听令与CPU的调度,那么我们把这个中间状态称之为可执行状态(RUNNABLE)也就是说它具备执行的资格,但是并没有真正的执行起来而是在等待CPU调度。
BLOCKED 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入 Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
WATING 一个正在等待的线程的状态。也称之为等待状态。造成线程等待的原因有两种,分别是 调用Object.wait()、join()方法。处于等待状态的线程,正在等待其他线程去执行一个特 定的操作。例如:因为wait()而等待的线程正在等待另一个线程去调用notify()或 notifyAll();一个因为join()而等待的线程正在等待另一个线程结束。
TIMED_WAITING
一个在限定时间内等待的线程的状态。也称之为限时等待状态。造成线程限时等待状态 的原因有三种,分别是:Thread.sleep(long),Object.wait(long)、join(long)。
TERMINATED
一个完全运行完成的线程的状态。也称之为终止状态、结束状态 ,会销毁所有线程。
线程池
可以将线程池理解为创建和装线程的池子
线程池的意义:
系统创建线程的成本比较高因为涉及到操作系统的交互,当程序中需要创建大量生存期很短暂的线程时,频繁创建和销毁线程对系统资源消耗较大,为提高性能便有了线程池。线程池在启动时会创建大量空闲线程,当向线程池提交任务时线程池就会启动一个线程执行任务,此线程执行完毕后线程并不会死亡而是再次返回到线程池为空闲状态并等待下一次任务的执行。
Executors默认线程池
1
//创建一个默认的线程池对象.池子中默认是空的.默认最多可以容纳int类型的最大值. ExecutorService executorService = Executors.newCachedThreadPool();
Executors创建指定上限的线程池
//创建指定上线的线程池,10参数是最大上限为10条线程 ExecutorService executorService = Executors.newFixedThreadPool(10);
ThreadPoolExecutor 线程池
创建线程池对象(此对象需要传入7个参数)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(核心线程数量,最大线程数量,空闲线程最 大存活时间,任务队列,创建线程工厂,任务的拒绝策略);
线程池对象需要传入七个参数的要求
参数一:核心线程数量--不能小于0
参数二:最大线程数量--不能小于等于0,最大数量要大于等于核心线程数量
参数三:空闲线程最大存活时间--不能小于0
参数四:时间单位--TimeUnit的时间单位
参数五:任务队列--不能为null
参数六:创建线程工厂--不能为null
参数七:拒绝任务策略--不能为null
举例
ThreadPoolExecutor pool = new ThreadPoolExecutor( 2,//核心线程数量 5,//最大线程数量 2,//空闲线程最大存活时间 TimeUnit.SECONDS,//时间单位 new ArrayBlockingQueue<>(10),//任务队列,此处可以有10个任务等待队列 Executors.defaultThreadFactory(),//创建线程工厂 new ThreadPoolExecutor.AbortPolicy()//任务拒绝策略,当线程不够用和等待队列满了,拒绝的策略 );
执行流程
线程池在创建之后并不会立刻创建线程,而是在任务过来之后,线程池会去判断当前线程池中的线程是否小于常驻线程,如果小于则创建线程,直到线程池中的线程不再小于常驻线程。任务交给线程去处理,如果常驻线程处理不过来之后会把多的任务交给阻塞队列,如果阻塞队列也满了就会开启最大线程,当最大线程和阻塞队列都满了就会根据拒绝策略拒绝任务,当流量放缓,核心线程能忙得过来,核心线程外的线程存活指定的时间便销毁了
线程池非默认任务拒绝策略
线程的据决策略有四个:抛异常、丢弃、丢弃队列中等待时间最长的、交给方法调者
(1)ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。是默认的 策略。
(2)ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常 这是不推荐的做法。
(3)ThreadPoolExecutor.DiscardOldestPolicy: 抛弃队列中等待最久的任务 然后把当前任务加入队列中。
(4)ThreadPoolExecutor.CallerRunsPolicy: 调用任务的run()方法绕过线程池直接执行。
线程池可执行的任务数量 = 任务队列容量+最大线程数
在日常工作中几乎不使用executors创建线程池,如果使用了可伸缩的线程池,整体线程数无法控制;也不使用单个线程线程池,也不使用固定长度大小的线程池。因为底层是一个linkedBlockingQueue,而这个Queue会开辟一个Integer.maxValue大小的阻塞队列,这样太占内存。