1.线程优化
1.1原因
- 一个线程大约栈1mb的运行内存,而我们的线程在执行完成后时等待系统回收的,会浪费大量运行内存
- 每次使用线程就创建,运行完后等待系统回收,频繁的创建与回收线程
- 代码编写冗余
1.2解决思路
提供一个可以控制线程创建,回收,复用线程的容器
线程池:拥有对线程进行创建,回收,复用的容器
1.3优点:
- 线程池中的线程是可以设置上限的
- 会复用线程
- 不会频繁的创建与回收线程
- 无需再去关心线程如何创建,只需要考虑每个线程执行的任务
2.线程池的体系结构
2.1Executor(接口)
提供的方法:
Void execute(Runnable command)
执行线程任务,相当于以前启动线程
子类或子接口:
2.1.1ExecutorService(子接口)
提供的方法:
Void shutdown();
作用:关闭线程池
Boolean isShutdown();
作用:获取线程池是否关闭,返回值为true表示关闭
Future<?> submit (Runnable task);
作用:提交线程任务,相当于执行线程任务
<T>Future<> submit(CallTable<T> task);
作用:提交线程任务,相当于执行线程任务
2.1.2子类或子接口
ScheduleExecutorService(ExectuorService的子接口)
概念:所有调度线程池的父接口
特有方法:
schedule( Runnable command, long delay, TimeUnit unit);
作用:延迟执行
参数:
Command:线程任务
Delay:延迟时间
Unit:时间单位
scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit);
作用:延迟重复执行
延迟多长时间后执行线程任务,间隔多久在此执行线程任务,重复
参数:
Command:线程任务
Initialdelay:延迟时间
Period:间隔时间(本次任务开始时间-上次任务开始时间=间隔时间)
如果上次任务执行时间(任务结束时间-任务开始时间)大于间隔时间,那么等上次任务执行完毕后,立即执行本次任务
Unit:时间单位
scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit);
作用:延迟重复执行
延迟多长时间后执行线程任务,间隔多久在此执行线程任务,重复
参数:
Command:线程任务
Initiadelay:延迟时间
Period:间隔时间(本息任务开始时间-上次任务结束时间)
Unit:时间单位
ThreadPoolExecutor(了解)
构造函数:
ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
imeUnit unit,
BlockingQueue workQueue)
ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory)
ThreadPoolExecutor(
int corePoolSize,//核心线程数量
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
CorePollSize:核心线程数量,即线程中最少有几个线程
maximumPoolSize:线程池最大线程数量
keepAliveTime:销毁时间,空闲线程多久没有时间被销毁,不会贤惠核心线程
unit:时间单位
workQueue:存放线程任务的队列
threadFactory:线程工厂
handler:复用机制与算法
3.线程工具类
作用:提供了多种线程池创建的静态方法
类名:Executor
提供的方法有:
Static ExecutorService newCachedThreadPool()
作用:创建一个可变线程池
特点:线程池中线程数量不限定,更具线程任务的数量多少进行变化
Static ExecutorService newFixedThreadPool(int nThreads)
作用:创建一个固定线程池
特点:
线程池中线程数量恒定
参数:
线程池中线程的数量
Static ExecutorService newFSingleThreadExecutor()
作用:创建一个单例线程池
特点:
线程池中只有一个线程
Static ExecutorService newworkStealingPool()
作用:创建一个抢占线程池
特点:
线程池中线程都是守护线程
有一个窃取算法
Static ScheduleExecutorService newScheduleThreadPool(int corePoolsize)
作用:创建一个调度线程池
参数:线程池中线程数量
特点:
线程任务可以延迟执行
Static ScheduleExecutorService newSingleThreadScheduleedExecutor()
作用:创建一个单例调度线程池
特点:创建一个调度线程池,该线程池中线程数量为1
4.线程池使用步骤
- 创建线程池
- 提交线程任务
可以使用:
Void execute(Runnable command)
Submit(Runnable task)
调度线程池还可以使用三个特有方法
- 关闭线程池
线程池对象.shutdown();
一般情况下:等线程池中线程执行完任务后关闭,调度线程池特有方法出除外
调度线程池执行延迟重复任务时,当线程池关闭,其找中的延迟重复任务也将被关闭
5.线程任务优化
案例:
使用;两个线程分别计算1~10的和与10的阶乘
然后线程结果相加
Jdk提供Callable接口,该接口是有返回值的线程任务
创建Callable对象
Callable 对象名=new Callable<返回值得数据类型>(){
Public 返回值的数据类型 call() throws Exception{
Return null;
}
}
获取Callable对象的计算结果
Submit方法有返回值,该返回值,该返回值为Future型
Callable的结果可以通过submit返回值的Future对象调用get方法
注意get方法会阻塞当前线程,直到对应的Callable得到结果
注意:
不能配合Thread类使用,可以在线程池中使用
6.锁
6.1锁的优点
便于使用
6.2体系结构
Lock(接口)
提供的方法
Void lock():上锁
Void unlock():开锁
子类:Reentrantlock(重写锁)
ReadWritelock(接口)
提供的方法
Lock readLock();获取一个读锁
Lock writeLock();获取一个写锁
注意:
读-读:异步
读-写:同步
写-写:同步
注意:
Synchronized做同步
Synchronized(锁对象){
要同步的代码
}
Lock做同步
Lock对象.lock();
要同步的代码
Lock对象.unlock();