线程的优化(重点)
优化的原因
1.一个线程存货的时候,所占内存大约为1mb
2.线程使用完之后会等待gc回收,此时大量的线程没有被回收,从而占据着内存
3.导致程序运行效率降低
结局思路
1.控制创建线程的数量
2.将使用玩的线程回收
3.将空闲的线程复用,从而提高线程的复用
jdk 提供了这个思路的工具: 就是线程池
线程池: Executor
简述:
一个用于管理,创建,复用,回收线程的容器,
优点:
1.创建线程不用在考虑其创建 ,复用,回收等问题,方便使用
2.节省运行内存,提高代码的执行效率
3.无需频繁的创建 和 销毁线程
体系:
Executor(接口):
子接口:
ExecutorService(接口)
方法:
shutdown(); 关闭线程池
submit();提交线程任务给线程池
子类:
ThreadPoolExecutor
...
子接口:
ScheduledExecutorService:线程调度池
线程池获取工具类
优点:
可以简单的获取线程池对象
获取线程池
固定线程池
概念;
获取一个线程数量固定的线程池
方法:
static ExecutorService newFixedThreadPool(线程数量)
可变线程池
概念:
获取一个线程数量不固定的线程池
方法:
static ExecutorService newCachedThreadPool()
单例线程池
作用;
获取线程数量为一的线程池
方法:
static ExecutorService newSingleThreadExecutor();
调度线程池
作用:
获取一个调度线程池
方法:
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
单例调度线程池
作用:
获取只有一个线程的调度线程池
方法:
static ScheduledExecutorService newSingleThreadScheduledExecutor()
抢占线程池(了解)
作用:
获取一个抢占线程池
方法:
static ExecutorService newWorkStealingPool()
特点:
1.jdk1.8出现
2.拥有特有的方法 - 调度
特有方法:
schedule:延迟多长时间后在执行任务
scheduleAtFixedRate:延迟多长时间后在执行任务,间隔多长时间后重复执行
间隔时间:前一次任务开始时间到本次任务开始时间
注意:
如果代码执行时间超过间隔时间,那么下次任务将在上次任务执行完后立即执行
scheduleWithFixedDelay:延迟多长时间后在执行任务,间隔多长后重复执行
间隔时间:上一次任务结束到本次任务开始时间,相当于没有间隔时间
ThreadPoolExecutor
概念:
可变线程池,固定线程池,单例线程池,获取到的线程池对象,本质就是该类的对象
因为在阿里白皮书中说到,为了深入了解线程池,建议所有开发人员使用ThreadPoolExecutor创建线程池对象
构造函数:
ThreadPoolExecutor( int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){}
参数解释:
参数一:
核心线程数量,线程池中的最小线程数量
参数二:
线程池中最大线程数量
参数三:
当非核心线程闲置多长时间会被系统回收
参数四:
时间单位
参数五:
存储线程池中执行的任务的集合
参数六:
线程工厂,在线程池中创建线程
参数七:
当线程池中线程任务多余线程时的策略
线程任务的优化
原因
因为线程任务在执行之后无法返回数据,所以对其进行优化
Callable
Callable 与 Thread 结合使用
步骤:
1.创建Callable 接口的子类对象
2.创建FutureTask 对象,并传入Callable 的子类对象
3.创建线程对象,并传入FutureTask 对象
4.启动线程
5.使用FutureTask 对象调用get()方法,获取Callable 中call()方法中的返回值
注意:
get () 方法会阻塞程序的执行,直到call()的方法执行完毕
Callable 与线程池结合使用
步骤:
1.创建线程池
2.创建线程任务对象,并将任务提交给线程池
3.获取线程任务中的返回值
4.关闭线程池
注意:
线程任务要有返回值只能是Callable 对象的任务对象,不能是Runnable 对象
锁的优化
原因
因为在使用synchronized时候,发现不是很方便,所以对其进行了优化
Lock
体系
接口; Lock
方法:
lock() 关闭锁
unlock() 释放锁
子类:
RenntrantLock : 重入锁
ReentrantReadWriteLock :
方法
readLock: 提供一个读的锁对象
writeLock : 提供一个写的锁对象
******************************面试可能会问****************************
- 读取和读取的锁对象是互相不干扰的
- 读取和写入的锁对象是互斥的
- 写入和写入的锁对象也是互斥的