okhttp(二)之线程池分析
Okhttp中使用到了ThreadPoolExecutor进行线程池的创建,
下面我们对ThreadPoolExecutor这个类的构造方法进行详细分析。
参数一:corePoolSize 核心线程数,表示线程池需要一直维护的数量,决定了任务是开辟新的线程还是放到workQueue任务队列中去。
参数二:maximumPoolSize 指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量。
参数三:keepAliveTime当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁。
参数四:unit keepAliveTime的单位。
参数五:workQueue任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种。
参数六:线程工厂,用于创建线程,一般用默认即可。
参数七:handler拒绝策略,当任务太多来不及处理时,如何拒绝任务。
注意
1.核心线程数不能大于最大线程数,否则会抛出异常。
2.正在执行的任务Runnable > corePoolSize --> 参数三/参数四 才会起作用。
3.核心线程满了,接下来进队列,队列也满了,创建新线程,直到达到最大线程数,之后再超出,会进入拒绝rejectedExecution
4.任务队列是可以指定大小的,默认是Integer.Max;
这也是为什么我们使用默认值时最大线程数仿佛不起作用一样;
当设置了任务队列大小后,所要执行的线程数大于任务队列并且所需要执行的线程数减去任务队列数量后不大于最大线程数时,超过队列部分,线程池会根据剩下所需要的线程数量创建线程。
此时线程存在的数量是根据超出队列部分的线程数或者最大线程数的较大值来决定的。
总结来说:核心线程满了,接下来进队列,队列也满了,创建新线程,直到达到最大线程数,之后再超出,会进入拒绝rejectedExecution
okhttp中线程池的使用
这里需要注意的是SynchronousQueue是一个没有容量的队列。即里面不会放入等待线程,会直接创建线程。
okhttp中核心线程数是0,最大线程数是根本用不完的数最大的int,闲置时间为60S,极大提到了okhttp的性能。
这么看okhttp是一个高并发的框架,容易造成OOM,所以,它采用了运行队列和等待队列来解决高并发的问题。
(1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造必须指定大小。其所含的对象是FIFO顺序排序的。
(2)LinkedBlockingQueue:大小不固定的BlockingQueue,若其构造时指定大小,生成的BlockingQueue有大小限制,不指定大小,其大小有Integer.MAX_VALUE来决定。其所含的对象是FIFO顺序排序的。
(3)PriorityBlockingQueue:类似于LinkedBlockingQueue,但是其所含对象的排序不是FIFO,而是依据对象的自然顺序或者构造函数的Comparator决定。
(4)SynchronizedQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成。
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
execute没有返回值,submit有返回值。execute是同步,submit是异步。
并发:在操作系统中,同一时间有多个进程处于已启动运行到运行完毕之间,且这几个程序是在同一个处理机上运行。
并行:当一个系统有多个cpu时,一个cpu执行一个进程,另一个cpu执行另一个进程,两个进程同时执行,不互相抢占资源。