目录
submit:提交一个任务到线程池,线程池会派遣一个空闲的线程来执行该任务。
shutdown()/shutdownNow():销毁线程池 ,
ThreadPoolExecutor子类的核心构造方法参数:
缓存线程池:同步阻塞队列,两个线程池同时获取和抛出一个任务。同步阻塞队列
3,读写锁(ReentrantReadWriteLock实现读写锁)
使用线程池的原因:
当有多个线程频繁的创建销毁,就会浪费大量的时间,用来创建线程池,保存一定数量的线程,来回收线程,保证重复使用,以此来减少线程的创建与销毁的时间。
JDK的线程池的使用
描述线程池的核心类:ThreadPoolExecutor(最常用的实现)
线程池的核心父接口:ExecuteService接口
这个类的构造方法,就是创建一个线程的所有核心参数,为了简化线程池的使用,jdk有新增加了几个类:
ThreaPoolExecute的核心方法:
execute:
submit:提交一个任务到线程池,线程池会派遣一个空闲的线程来执行该任务。
shutdown()/shutdownNow():销毁线程池 ,
public static void main(String[] args) {
//创建固定大小线程池
ExecutorService pool1 = Executors.newFixedThreadPool(10);
//创建定时线程池
// ExecutorService pool2 = Executors.newScheduledThreadPool(10);
// //创建可变大小线程池
// ExecutorService pool3 = Executors.newCachedThreadPool();
// //创建只有一个线程的线程池
// ExecutorService pool4 = Executors.newSingleThreadExecutor();
pool1.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
线程的执行:除了定时线程池,其他的线程池都是调用submit方法,定时线程池也可以调用submit方法来执行任务。
ExecutorService pool1 = Executors.newFixedThreadPool(10);
//创建定时线程池
ScheduledExecutorService pool2 = Executors.newScheduledThreadPool(10);
// //创建可变大小线程池
// ExecutorService pool3 = Executors.newCachedThreadPool();
// //创建只有一个线程的线程池
// ExecutorService pool4 = Executors.newSingleThreadExecutor();
pool1.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
pool1.shutdown();
pool2.schedule(new Runnable() {
@Override
public void run() {
System.out.println("三秒后打印"+123);
}
},3000,TimeUnit.MILLISECONDS);
pool2.shutdown();
}
ThreadPoolExecutor子类的核心构造方法参数:
线程池的工作流程:
当调用submit提交一个新任务时:
1,判断核心线程是否到达最大数量:
a,没有到达最大数量,创建一个新的线程,放到核心线程中
b,到达最大数量 ,执行2
2,判断工作队列是否已满
a,blockingQueue未满,直接将任务入队列
b,若队列已满,执行3
3,判断当前线程数量,是否达到最大线程数
a,未达到,创建临时线程,执行任务
b,达到最大线程数量,执行4
4,拒绝策略:
固定大小线程池的源码
缓存线程池:同步阻塞队列,两个线程池同时获取和抛出一个任务。同步阻塞队列
单一线程池:
延迟线程池:
阿里编码规范,自定义线程数量大小,避免使用系统线程池。
采用锁的策略:
1,乐观锁:
每次读写数据,认为线程不会发生阻塞,一般来说,一般只有在更新数据时,判断是否冲突,若没有冲突,直接更新,若冲突(多线程同时更新数据),解决冲突。
2,悲观锁:
认为每次读写数据,都会冲突,每次在数据读写时,都会上锁,保证每次只有一个线程读写数据,确保数据绝对安全。
乐观锁的实现:采用版本号机制实现乐观锁(CAS)
一般锁的实现:采用乐观锁与悲观锁并用的策略
3,读写锁(ReentrantReadWriteLock实现读写锁)
多线程在读操作时,不会冲突,写操作时,才会冲突。
并发读锁,并发
并发写锁:互斥,串行
读写并行:先写在读,串行。
4,重量级锁和轻量级锁:
轻量级锁:由cpu调度,自旋方式
重量级锁:需要os调用的参与,当获取锁失败,进入阻塞,从用户态切换到核心态。
轻量级锁的实现:采用自旋方式
自旋锁:当获取不到锁,就一直在循环,不让出cpu,不阻塞,不从用户态切换到核心态,如果一旦对象被释放,就立即对对象进行加锁。
5,公平锁与非公平锁
公平锁:先来先服务的线程调度算法
非公平锁:锁被释放,所有线程同时竞争。synchronized为非公平锁
锁的升级:
偏向锁 ——> 轻量级锁 ——> 重量级锁。