当前位置: 首页 > 知识库问答 >
问题:

ThreadPoolExecutor修复了具有自定义行为的线程池

阎德宇
2023-03-14

我不熟悉这个话题。。。我正在使用由Executors创建的ThreadPoolExecutor。新的FixedThreadPool(10),池满后,我开始得到一个RejectedExecutionException。有没有办法“强制”执行者将新任务置于“等待”状态,而不是拒绝它并在池释放时启动它?

谢啦

与此相关的问题https://github.com/evilsocket/dsploit/issues/159

涉及的代码行https://github.com/evilsocket/dsploit/blob/master/src/it/evilsocket/dsploit/net/NetworkDiscovery.java#L150

共有3个答案

戚兴思
2023-03-14

基于前面的建议,您可以使用阻塞队列构造一个固定大小的ThreadPoolExecutor。如果随后提供自己的拒绝执行处理程序(RejectedExecutionHandler),将任务添加到阻塞队列中,则其行为将如所述。

下面是一个如何构建这样一个执行者的示例:

int corePoolSize    = 10;
int maximumPoolSize = 10;
int keepAliveTime   =  0;
int maxWaitingTasks = 10;

ThreadPoolExecutor blockingThreadPoolExecutor = new ThreadPoolExecutor(
        corePoolSize, maximumPoolSize,
        keepAliveTime, TimeUnit.SECONDS,
        new ArrayBlockingQueue<Runnable>(maxWaitingTasks),
        new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    executor.getQueue().put(r);
                } catch (InterruptedException e) {
                    throw new RuntimeException("Interrupted while submitting task", e);
                }
            }
        });
傅朗
2023-03-14

线程很有可能调用export,将mStoped设置为false并关闭执行程序,但是:

  • 正在运行的线程可能处于while(!mStopped)循环的中间,并尝试向执行器提交任务,该执行器已在退出时关闭

我建议:

  • 使易挥发
  • 处理执行器在循环中间关闭的情况(例如,通过捕获RejectedExecutionException,或者更好:在while循环之后关闭执行器,而不是在exit方法中关闭)
宗弘扬
2023-03-14

如果使用执行器。newFixedThreadPool(10) 它对任务进行排队,等待线程就绪。

此方法为

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

如您所见,使用的队列是无界的(这本身可能是个问题),但这意味着队列永远不会填满,您永远不会被拒绝。

顺便说一句:如果您有CPU绑定的任务,可以选择最佳线程数

int processors = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(processors);

一个可以说明这种情况的测试类

public static void main(String... args) {
    ExecutorService es = Executors.newFixedThreadPool(2);
    for (int i = 0; i < 1000 * 1000; i++)
        es.submit(new SleepOneSecond());

    System.out.println("Queue length " + ((ThreadPoolExecutor) es).getQueue().size());
    es.shutdown();
    System.out.println("After shutdown");
    try {
        es.submit(new SleepOneSecond());
    } catch (Exception e) {
        e.printStackTrace(System.out);
    }
}

static class SleepOneSecond implements Callable<Void> {
    @Override
    public Void call() throws Exception {
        Thread.sleep(1000);
        return null;
    }
}

印刷品

Queue length 999998
After shutdown
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@e026161 rejected from java.util.concurrent.ThreadPoolExecutor@3e472e76[Shutting down, pool size = 2, active threads = 2, queued tasks = 999998, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2013)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:816)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1337)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:132)
    at Main.main(Main.java:17)
 类似资料:
  • 我正在编写一个定制的ThreadPoolExecutor,具有以下额外功能:- > 如果有理想的线程,并且随着任务的到来,将该任务分配到队列中,而不是将其添加到队列中。 如果所有线程(最大池大小)都忙,则在新任务到来时,使用RejectionHandler的reject方法将它们添加到队列中 我已经重写了线程池执行程序的java 1.5版本的执行方法。 新守则如下:- 遗留代码如下所示:- 现在正

  • SOFARPC 支持自定义业务线程池。可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的。多个服务可以共用一个独立的线程池。 SOFARPC 要求自定义线程池的类型必须是 com.alipay.sofa.rpc.server.UserThreadPool。 XML 方式 如果采用 XML 的方式发布服务,可以先设定一个 class 为 com.alipay.sof

  • 编辑:我需要实现的是允许客户在购物车页面上留下与每个购物车项目相关的信息,这些信息将显示在购物车/结账/订单中...问题是,当我在购物车中有相同产品的两个不同变化时,我得到了它们的重复消息(最后一个变化消息)。 这是我代码中的一段: 问题:这个循环为购物车页面上有变化的产品提供了重复的自定义post元数据 到目前为止,我的结论是:我理解这是因为update_post_meta()正在通过更新元值,

  • 我希望在JavaFX中有一个完全定制的窗口。与此处完全相同的问题: https://code.msdn.microsoft.com/WPF-styling-a-Window-in-fcf4e4ce 使用未DECORATED JavaFX阶段,我必须自己实现所有窗口功能-并失去所有本机窗口行为,包括: 拖动到顶部时最大化 拖动到两侧时的并排视图 单击任务栏时最小化/最大化 我可以以某种方式访问原生W

  • 是否可以为Java8并行流指定自定义线程池?我到处都找不到它。 如果我不能为不同的模块使用不同的线程池,这就意味着我不能在大多数真实世界的情况下安全地使用并行流。 请尝试以下示例。有些CPU密集型任务在单独的线程中执行。这些任务利用并行流。第一个任务被打破,因此每一步需要1秒(通过线程Hibernate模拟)。问题是其他线程会被卡住,等待中断的任务完成。这是一个虚构的示例,但假设一个servlet

  • 由来 在JDK中,提供了Executors用于创建自定义的线程池对象ExecutorService,但是考虑到线程池中存在众多概念,这些概念通过不同的搭配实现灵活的线程管理策略,单独使用Executors无法满足需求,构建了ExecutorBuilder。 概念 corePoolSize 初始池大小 maxPoolSize 最大池大小(允许同时执行的最大线程数) workQueue 队列,用于存在