多线程
线程池原理
参考资料:https://blog.csdn.net/weixin_42765975/article/details/106163487
以固定线程池举例:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
可以看到返回的是一个ThreadPoolExecutor对象,核心线程数和是最大线程数都是传入的参数,存活时间是0,时间单位是毫秒,阻塞队列是以无界队列LinkedBlockingQueue举例。取不到任务就直接回收线程
线程池参数详解
https://blog.csdn.net/xiaojin21cen/article/details/87359148
keepAliveTime、TimeUnit 存活时间和单位
keepAliveTime :表示空闲线程的存活时间。
TimeUnit unit :表示keepAliveTime的单位。
为了解释 keepAliveTime 的作用,我们在上述情况下做一种假设。假设线程池这个单位已经招了些临时工,但新任务没有继续增加,所以随着每个员工忙完手头的工作,都来workQueue领取新的任务(看看这个单位的员工多自觉啊)。随着各个员工齐心协力,任务越来越少,员工数没变,那么就必定有闲着没事干的员工。这样的话领导不乐意啦,但是又不能轻易fire没事干的员工,因为随时可能有新任务来,于是领导想了个办法,设定了 keepAliveTime,当空闲的员工在 keepAliveTime 这段时间还没有找到事情干,就被辞退啦,毕竟地主家也没有余粮啊!当然辞退到 corePoolSize 个员工时就不再辞退了,领导也不想当光杆司令啊!
Callable、Runnable
参考资料:https://developer.aliyun.com/article/604983
callable任务被包装成RunnableFuture对象,通过线程池execute方法提交任务。
FutureTask的两个构造函数
RunnableFuture接口继承了Futrue和Runnable。然后FutureTask实现了RunnableFuture。FutureTask通过run方法计算,而get方法来获取结果。
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
public class FutureTask<V> implements RunnableFuture<V>
总结如下图Callable其实是Future的成员变量,最后会将Runnable转成Callable: