线程的生命周期
线程的六个状态:NEW(新生态) RUNNALBE(运行态) BLOCKED(阻塞态) WAIT(等待) TIME_WAIT(超时等待) TERMINATED(终止态)
一个线程完整的生命周期中通常需要经历下面五种状态:
(1)新生:当一个Thread类或其子类对象被声明创建时,线程对象处于新建态。
(2)就绪:新生的线程start()之后,进入线程队列等待CPU时间片,此时它拥有抢CPU的能力,即具备运行条件,只是还没有分配到CPU资源。
(3)运行:当就绪的线程被调度后,获得了CPU资源就进入了运行态,run()方法定义了线程的功能和操作。
(4)阻塞:某种情况,线程被认为挂起,让出CPU并中断自己的执行,进入阻塞态
(5)死亡:线程在完成了自己的任务后,强制性中断或者异常中断导致线程结束(死亡)
线程通信
线程通信的例子:多线程交替打印
涉及到的方法:
(1)wait():调用此方法后,线程会主动放弃CPU,进入阻塞态
(2)notify():调用此方法后,wait的线程会被唤醒,进入就绪态重新抢夺CPU(单一唤醒,多个线程按优先级排序)
(3)notifyAll():调用此方法后,所有wait的线程都会被唤醒进入就绪态重新抢夺CPU。
sleep()和wait()有何异同?
相同点:调用两个方法都会使线程进入阻塞态。
不同点:
(1)两个方法来自不同的类,sleep()来自Thread类,而wait()来自Object类
(2)两个方法声明的位置不同,sleep()可在任意位置调用,而wait()只能在同步代码块中调用。
(3)sleep()只是线程暂时的休眠,并不会释放掉同步监视器(锁),而wait()会释放同步监视器。
线程池相关
线程池的优点:
(1)效率高(提高响应速度)因为池中就准备好我们需要的线程,拿来就用,不用新建。
(2)节省资源(减少资源的消耗)新建线程和销毁线程会消耗资源。
(3)线程统一集中便于管理。
线程池的三大操作:
单线程
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
给定线程的池
ExecutorService executorService2 = Executors.newFixedThreadPool(5);
可伸缩的池
ExecutorService executorService3 = Executors.newCachedThreadPool();
阿里开发手册不允许使用Executors创建线程池,
OOM(OutOfMemoryError):内存溢出错误
FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
CachedThreadPool和ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
线程池七大参数
corePoolSize : 核心线程池的大小
maximumPoolSize:池中运行的最多线程数
keepAliveTime:线程存活时间
TimeUnit : 时间的单位
BlockingQueue 阻塞队列
ThreadFactory : 线程工厂用于生产线程
RejectedExecutionHandler :拒绝策略(四种) 默认为:AbortPolicy
(1)ThreadPoolExcutor.AbortPolicy 如果线程数大于 maximumPoolSize+BlockingQueue.capacity(阻塞队列的长度) 则会抛出异常
(2)ThreadPoolExcutor.CallerRunsPolicy 哪里来的回哪里去,多出来的会让主线程执行
(3)ThreadPoolExcutor.DiscardPolicy 队列满了,丢掉任务,不会抛出异常
(4)ThreadPoolExcutor.DiscardOldestPolicy 队列满了,尝试去和最早的线程竞争,不会抛异常
银行办理业务形象描述七大参数
任务提交至线程池的处理过程
最大线程如何定义
CPU密集型:几核的CPU就定多少 可以保证CPU效率最高
可以使用Runtime.getRuntime().availableProcessors()查看核数直接传给maximumPoolSize
IO密集型: 判断十分耗费IO的线程;有几个大型任务就定为多少