刚开始的时候,没有线程池的概念,单线程慢慢满足不了我们的系统开发需求,我们就想多线程开发,但是新来一个任务就创建一个线程,这样肯定不行的,因为线程的创建需要有一定的资源,所以造一个东西能够线程复用,这就是线程池
//表示线程池的状态以及数量 状态初始化为Running状态,运行线程数初始话为0 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //状态为以下五种 private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS;
知识点:
q:线程池状态为用一个AtomicInteger的ctl字段表示两个变量的含义,为什么这样干
A:一个字段表示两个含义,这样可以避免占用锁资源,我们在下面阅读源码的时候可以看到,线程池在进行一系列骚操作去逻辑判断的时候,经常需要判断线程池的状态已经当前线程数这两个变量值去做逻辑操作,源码用一个变量存储两个变量含义,可以避免在相关决策的时候,出现不一致情况,在修改两个变量含义的时候,不需要占用锁资源去维护,线程池还非常贴心的封装两个函数runStateOf()获取线程池当前运行状态和workerCountOf()获取当前线程数这两个函数或者这两个变量的值。
JDK源码中给我们封装好了几个创建好的线程池,我们一起来了解一下。
Executors.newFixedThreadPool(int i)
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
创建一个拥有 i 个线程的线程池,创建一个定长线程池,可控制线程数最大并发数,超出的线程会在阻塞队列中等待
Executors.newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
Executors.newCacheThreadPool()
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
Executors.newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
通过源码可以知道,其实就是底层都是使用ThreadPoolExecutor传递不同的参数,虽然JDK默认给我们封装创建好线程池,但是因为很多时候很多时候不能满足我们的需求,阿里开发文档也建议我们自己创建线程池,一起跟着程序员fly公众号研究一下ThreadPoolExecutor源码吧
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory, RejectedExecutionHandler handler)
定义一个线程池,通过代码观察一下现象
public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 4, 5L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1)); for (int i = 0; i <4; i++) { threadPoolExecutor.execute(new Runnable() { @Override public void run() { System.out.println("线程池名称"+Thread.currentThread().getName() + "线程池状态," + threadPoolExecutor.toString()); } }); } }
运行结果
结果分析
我们自定义了一个线程池,通过for循环4次打印线程信息,线程池条件 最大线程的数量为4,阻塞队列为1,核心线程池为3,
结果显示active thread最大为3,表明没有创建非核心线程,4个任务,三个核心线程处理,一个放入队列中
public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 4, 5L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1)); for (int i = 0; i <5; i++) { threadPoolExecutor.execute(new Runnable() { @Override public void run() { System.out.println("线程池名称"+Thread.currentThread().getName() + "线程池状态," + threadPoolExecutor.toString()); } }); } }
运行结果
结果分析
我们自定义了一个线程池,条件是 通过5个for循环打印线程信息,最大线程的数量为4,阻塞队列为1,核心线程池为3,
结果可以看到active thread=4过,创建额外线程1个,5个任务,3个核心线程处理,1个阻塞队列中,1个非核心线程处理,总线程数为3+1=4,没超过最大
public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 4, 5L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1)); for (int i = 0; i <6; i++) { threadPoolExecutor.execute(new Runnable() { @Override public void run() { System.out.println("线程池名称"+Thread.currentThread().getName() + "线程池状态," + threadPoolExecutor.toString()); } }); } }
运行结果
结果分析
我们自定义了一个线程池,条件是 通过6个for循环打印线程信息,最大线程的数量为4,阻塞队列为1,核心线程池为3,
结果可以看到active thread=4过,说明创建额外的线程完成任务了,3个核心线程 1个队列,1个非核心线程处理,还剩1个抛出异常
自己的情况是这样的,本人学历是双非本科,enen,嗯嗯就是突然感觉或许可以把自己变的更好一点,也希望想找一些小伙伴一起学习,所以把自己平常自己学习到的一些东西分享出来,能帮助各位更好。