JDK的java.util.concurrent.ThreadPoolExecutor允许您将任务提交到线程池,并使用BlockingQueue来保存提交的任务。 如果您要提交数千个任务,请指定一个“绑定”队列(即最大容量的队列),否则JVM可能会耗尽内存。 您可以设置RejectedExecutionHandler来处理队列已满时发生的情况,但是仍然有待提交的任务。

这里是你展示如何使用一个简单的例子ThreadPoolExecutor具有BlockingQueue容量1000 CallerRunsPolicy确保,当队列已满时,其他任务将由提交线程处理。

int numThreads = 5;
ExecutorService exec = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(1000),new ThreadPoolExecutor.CallerRunsPolicy());

这种方法的问题在于,当队列已满时,向池提交任务的线程会变得忙于执行任务本身,在此期间,队列可能会变空并且池中的线程可能会变得空闲。 这不是很有效。 我们希望一直保持线程池繁忙,并且工作队列始终处于饱和状态。

有多种解决方案。 其中之一是使用自定义的Executor ,该Executor在队列已满时会阻塞(从而阻止其他任务提交到池)。 BlockingExecutor的代码如下所示。 它基于Brian Goetz,2006年的BoundedExecutor示例。Java Concurrency in Practice。 1版。 Addison-Wesley专业。 (第8.3.3节) 。

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** An executor which blocks and prevents further tasks from* being submitted to the pool when the queue is full.* <p>* Based on the BoundedExecutor example in:* Brian Goetz, 2006. Java Concurrency in Practice. (Listing 8.4)*/
public class BlockingExecutor extends ThreadPoolExecutor {private static final Logger LOGGER = LoggerFactory.getLogger(BlockingExecutor.class);private final Semaphore semaphore;/*** Creates a BlockingExecutor which will block and prevent further* submission to the pool when the specified queue size has been reached.** @param poolSize the number of the threads in the pool* @param queueSize the size of the queue*/public BlockingExecutor(final int poolSize, final int queueSize) {super(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());// the semaphore is bounding both the number of tasks currently executing// and those queued upsemaphore = new Semaphore(poolSize + queueSize);}/*** Executes the given task.* This method will block when the semaphore has no permits* i.e. when the queue has reached its capacity.*/@Overridepublic void execute(final Runnable task) {boolean acquired = false;do {try {semaphore.acquire();acquired = true;} catch (final InterruptedException e) {LOGGER.warn("InterruptedException whilst aquiring semaphore", e);}} while (!acquired);try {super.execute(task);} catch (final RejectedExecutionException e) {semaphore.release();throw e;}}/*** Method invoked upon completion of execution of the given Runnable,* by the thread that executed the task.* Releases a semaphore permit.*/@Overrideprotected void afterExecute(final Runnable r, final Throwable t) {super.afterExecute(r, t);semaphore.release();}
}
参考:我们的JCG合作伙伴 Fahd Shariff在fahd.blog博客上使用BlockingExecutor进行节流任务提交 。

翻译自: https://www.javacodegeeks.com/2013/11/throttling-task-submission-with-a-blockingexecutor-2.html

用BlockingExecutor限制任务提交相关推荐

  1. 提交时是使用防抖还是节流_使用BlockingExecutor进行节流任务提交

    提交时是使用防抖还是节流 JDK的java.util.concurrent.ThreadPoolExecutor允许您将任务提交到线程池,并使用BlockingQueue来保存提交的任务. 如果要提交 ...

  2. 解决gitte提交报错 error: GE007: Your push would publish a private email address.

    错误情况: gitte提交报错,无法提交上去,报错如下: remote: Powered by GITEE.COM [GNK-6.0] remote: error: GE007: Your push ...

  3. form表单提交前进行ajax或js验证,校验不通过不提交

    在使用form表单进行提交数据前,需要进行数据的校验->表单的校验(如:两次密码输入是否相同)+后台数据的校验(如:账号是否存在),这个时候,如果哪步校验不通过,表单将停止提交,同时避免后台主键 ...

  4. 用js方法做提交表单的校验

    基础知识: 原始提交如下: <form action="<%=basePath %>puser/register" method="post" ...

  5. Spring AOP + Redis解决重复提交的问题

    Spring AOP + Redis解决重复提交的问题 用户在点击操作的时候,可能会连续点击多次,虽然前端可以通过设置按钮的disable的属性来控制按钮不可连续点击,但是如果别人拿到请求进行模拟,依 ...

  6. 后端怎么防止重复提交?(常用的做法)

    后端怎么防止重复提交?(常用的做法) 客户端的抖动,快速操作,网络通信或者服务器响应慢,造成服务器重复处理.防止重复提交,除了从前端控制,后台也需要控制.因为前端的限制不能解决彻底.接口实现,通常要求 ...

  7. form表单提交编码的问题

    浏览器在form提交后,会生成一个HTTP的头部信息"content-type",标准规定其形式为Content-type: application/x-www-form-urle ...

  8. js异步提交form表单的解决方案

    1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span sty ...

  9. 提交表单自动刷新_Web自动化测试:元素的基础操作和浏览器基础操作

    上一节,我们了解了如何定位元素,其实也有涉及对于元素的操作,这一节我们就详细的介绍一下对于元素的操作和对于浏览器的一些操作 一.对于元素的基础操作: clear():清除输入框内的文本 send_ke ...

最新文章

  1. 14.Python抠图脚本
  2. 爬虫python代码-一则python3的简单爬虫代码
  3. XCode4.3.3 + iOS5.1 无证书开发并生成app、ipa文件
  4. unity android 符号表,记录腾讯bugly关于符号表的配置
  5. 图的深度优先遍历+图解
  6. c语言经典游戏,C语言——经典小游戏——打砖块
  7. “后T+0”时代:基金电商人以变应变
  8. Python小白的数据库入门
  9. 台式计算机有哪些部分组成,常用台式电脑的基本组成
  10. 颜文字风波+选颜文字游戏
  11. nssl 1467.U
  12. 小米2A com.android.phone,104.android 简单的检查小米手机系统和华为手机系统是否打开通话自动录音功能,跳转通话录音页面...
  13. python猴子分桃子的数学题_小学奥数猴子分桃练习及答案【三篇】
  14. 【Android】 Firebase登录、FCM、Google Play支付、adbrix、ONEStore、Galaxy Store、Google Install Referrer
  15. Linux防火墙关闭方法
  16. Kubernetes安装报错nodeRegistration.name: Invalid value: “vm_0_14_centos“: a DNS-1123 subdomain
  17. 网络技巧|远程桌面连接不上的多种解决方案!
  18. 赛酷软件测试自学,赛酷ocr怎么用 赛酷ocr使用方法
  19. java thirteen线程同步机制
  20. 1) DAC 数模转换器 2) TIA 跨阻放大器 3) ADC 模数转换器

热门文章

  1. strcompare php,PHP中的startswith()和endsWith()函数
  2. java 组件化_(原创)搭建一个组件化的监控平台
  3. 使用log4j2打印mybatis的sql执行日志
  4. mybatis generator Unknown system variable 'query_cache_size' 的解决方法
  5. Access restriction: The type 'BASE64Encoder' is not API 的解决方法
  6. 本地方法(JNI)——数值参数与返回值
  7. ibm liberty_使用Open Liberty的开发模式最大程度地缩短周转时间
  8. apache camel_Apache Camel Intellij IDEA插件的工作已开始
  9. android 揭示动画_揭示垃圾收集暂停的时间长度
  10. c#中overlord实例_具有Overlord的WildFly 8.1中的API管理