7.为什么用线程池?解释下线程池参数?
用线程池的原因:
1、降低资源消耗;提⾼线程利用率,降低创建和销毁线程的消耗。
2、提⾼响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,再执行。
3
、提⾼线程的可管理性;线程是稀缺资源,使用线程池可以统一分配调优监控。
线程池参数 :
1.corePoolSize 代表核心线程数,也就是正常情况下创建工作的线程数,这些线程创建后并不会消除,而是一种常驻线程 。
2.maxinumPoolSize
代表的是最⼤线程数,它与核心线程数相对应,表示最大允许被创建的线程数,比如当前任务较多,将核心线程数都用完了,还无法满足需求时,此时就会创建新的线程,但是线程池内线程总数不会超过最⼤线程数。
3.keepAliveTime
、
unit
表示超出核⼼线程数之外的线程的空闲存活时间,也就是核心线程
不会消除,但是超出核心线程数的部分线程如果空闲⼀定的时间则会被消除,我们可以通过
setKeepAliveTime
来设置空闲时间。
4.workQueue 用
来存放待执行的任务,假设我们现在核心线程都已被使用,还有任务进来则全部 放⼊队列,直到整个队列被放满但任务还再持续进⼊则会开始创建新的线程。
5.ThreadFactory
实际上是⼀个线程工厂,⽤来⽣产线程执行任务。我们可以选择使⽤默认的创建工厂,产⽣的线程都在同一个组内,拥有相同的优先级,且都不是守护线程。当然我们也可以选 择⾃定义线程工厂,一般我们会根据业务来制定不同的线程工厂。
6.Handler
任务拒绝策略,有两种情况,第⼀种是当我们调⽤
shutdown
等⽅法关闭线程池
后,这时候即使线程池内部还有没执行完的任务正在执行,但是由于线程池已经关闭,我们再继续
想线程池提交任务就会遭到拒绝。另⼀种情况就是当达到最⼤线程数,线程池已经没有能⼒继续处
理新提交的任务时,这是也就拒绝。
8.线程池的底层⼯作原理
线程池内部是通过队列+线程实现的,当我们利用线程池执行任务时:
1. 如果此时线程池中的线程数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2. 如果此时线程池中的线程数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。
3. 如果此时线程池中的线程数量⼤于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量⼩于maximumPoolSize,建新的线程来处理被添加的任务。
4. 如果此时线程池中的线程数量⼤于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
5. 当线程池中的线程数量⼤于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
9.ReentrantLock中tryLock()和lock()⽅法的区别
1. tryLock()表示尝试加锁,可能加到,也可能加不到,该方法不会阻塞线程,如果加到锁则返回 true,没有加到则返回false。
2. lock()表示阻塞加锁,线程会阻塞直到加到锁,方法也没有返回值。
10.Sychronized和ReentrantLock的区别
1. sychronized是一个关键字,ReentrantLock是一个类。
2. sychronized会自动的加锁与释放锁,ReentrantLock需要程序员手动加锁与释放锁。
3. sychronized的底层是JVM层⾯的锁,ReentrantLock是API层面的锁。
4. sychronized是非公平锁,ReentrantLock可以选择公平锁或非公平锁。
5. sychronized锁的是对象,锁信息保存在对象头中,ReentrantLock通过代码中int类型的state标识来标识锁的状态。
6. sychronized底层有一个锁升级的过程。
11.谈谈你对AQS的理解,AQS如何实现可重入锁?
1. AQS是⼀个JAVA线程同步的框架。是JDK中很多锁工具的核心实现框架。
2. 在AQS中,维护了⼀个信号量state和⼀个线程组成的双向链表队列。其中,这个线程队列,就是用来给线程排队的,而state就像是一个红绿灯,用来控制线程排队或者放行的。 在不同的场景下,有不用的意义。
3. 在可重入锁这个场景下,state就⽤来表示加锁的次数。
0
标识无锁,每加一次锁,state就加
1
。释放锁state就减1
。
12.ThreadLocal的底层原理
1. ThreadLocal是Java中所提供的线程本地存储机制,可以利用该机制将数据
缓存在某个线程内部
,该线程可以在任意时刻、任意方法中获取缓存的数据
2. ThreadLocal底层是通过
ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal对象)中都存在一个ThreadLocalMap,Map的key为ThreadLocal对象,Map的value为需要缓存的值
3. 如果在线程池中使用ThreadLocal会造成内存泄漏,因为当ThreadLocal对象使用完之后,应该要把设置的key,value,也就是Entry对象进行回收,但线程池中的线程不会回收,而线程对象是通过强引用指向ThreadLocalMap,ThreadLocalMap也是通过强引⽤指向Entry对象,线程不被回收,Entry对象也就不会被回收,从而出现内存泄漏,解决办法是,在使⽤了ThreadLocal对象之后,手动调用ThreadLocal的remove⽅法,手动清楚Entry对象。
4. ThreadLocal经典的应⽤场景就是连接管理(一个线程持有一个连接,该连接对象可以在不同的方法之间进行传递,线程之间不共享同一个连接)。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后还为大家献上一个小程序,里面不仅有海量的面试题,还可以根据自己的级别在线刷题。