🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 任务阻塞队列 ![](https://img.kancloud.cn/13/d6/13d64359f30173ea25b4911ee63b5165_1530x546.png) **它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列;** ### SynchronousQueue 1、**直接提交队列**:设置为`SynchronousQueue`队列,`SynchronousQueue`是一个特殊的`BlockingQueue`,它没有容量,每执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒,反之每一个删除操作也都要等待对应的插入操作。 使用`SynchronousQueue`队列,提交的任务不会被保存,总是会马上提交执行。如果用于执行任务的线程数量小于`maximumPoolSize`,则尝试创建新的进程,如果达到`maximumPoolSize`设置的最大值,则根据你设置的`handler`执行拒绝策略。因此这种方式你提交的任务不会被缓存起来,而是会被马上执行,在这种情况下,你需要对你程序的并发量有个准确的评估,才能设置合适的`maximumPoolSize`数量,否则很容易就会执行拒绝策略; ### ArrayBlockingQueue 2、**有界的任务队列**:有界的任务队列可以使用`ArrayBlockingQueue`实现,如下所示: ``` pool = new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); ``` 使用`ArrayBlockingQueue`有界任务队列,若有新的任务需要执行时,线程池会创建新的线程,直到创建的线程数量达到`corePoolSize`时,则会将新的任务加入到等待队列中。若等待队列已满,即超过`ArrayBlockingQueue`初始化的容量,则继续创建线程,直到线程数量达到`maximumPoolSize`设置的最大线程数量,若大于`maximumPoolSize`,则执行拒绝策略。在这种情况下,线程数量的上限与有界任务队列的状态有直接关系,如果有界队列初始容量较大或者没有达到超负荷的状态,线程数将一直维持在`corePoolSiz`e以下,反之当任务队列已满时,则会以`maximumPoolSize`为最大线程数上限。 ### LinkedBlockingQueue 3、**无界的任务队列**:无界任务队列可以使用`LinkedBlockingQueue`实现,如下所示: ``` pool = new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); ``` 使用无界任务队列,线程池的任务队列可以无限制的添加新的任务,而线程池创建的最大线程数量就是你`corePoolSize`设置的数量,也就是说在这种情况下`maximumPoolSize`这个参数是无效的,哪怕你的任务队列中缓存了很多未执行的任务,当线程池的线程数达到`corePoolSize`后,就不会再增加了;若后续有新的任务加入,则直接进入队列等待,当使用这种任务队列模式时,一定要注意你任务提交与处理之间的协调与控制,不然会出现队列中的任务由于无法及时处理导致一直增长,直到最后资源耗尽的问题。 ### PriorityBlockingQueue 4、**优先任务队列**:优先任务队列通过`PriorityBlockingQueue`实现: 任务会按优先级重新排列执行,且线程池的线程数一直为`corePoolSize`,也就是只有一个。 `PriorityBlockingQueue`其实是一个特殊的无界队列,它其中无论添加了多少个任务,线程池创建的线程数也不会超过`corePoolSize`的数量,只不过其他队列一般是按照先进先出的规则处理任务,而`PriorityBlockingQueue`队列可以自定义规则根据任务的优先级顺序先后执行。 其实`LinkedBlockingQueue`也是可以设置界限的,它默认的界限是`Integer.MAX_VALUE`。同时也支持也支持构造的时候设置队列大小。