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

更改ThreadPoolExecutor

翟宏放
2023-03-14

当一个任务要执行时,它会被插入到队列中,当队列返回false时,将为其执行创建一个新线程。当前位于池中的空闲线程不会被拾取。原因是任务从getTask()方法分配给空闲线程,该方法从队列中选择任务。所以我的问题是如何改变这种行为,以便如果线程是空闲的,如何确保为空闲线程分配执行任务,而不是创建新线程??

下面的输出将使其更加清楚:-

Task 46 ends
Active Count: 0 Pool Size : 3 Idle Count: 3 Queue Size: 0
Task 47 ends
Active Count: 0 Pool Size : 3 Idle Count: 3 Queue Size: 0
Task 48 ends
Active Count: 0 Pool Size : 3 Idle Count: 3 Queue Size: 0
Active Count: 1 Pool Size : 4 Idle Count: 3 Queue Size: 0
Task 49 ends
Active Count: 2 Pool Size : 5 Idle Count: 3 Queue Size: 0
Task 50 ends
Active Count: 2 Pool Size : 5 Idle Count: 3 Queue Size: 0

代码文件如下:-

 public void execute(Runnable command) {
    System.out.println("Active Count: " + getActiveCount()
            + " Pool Size : " + getPoolSize() + " Idle Count: "
            + (getPoolSize() - getActiveCount())+" Queue Size: "+getQueue().size());
          if (command == null)
              throw new NullPointerException();
          for (;;) {
              if (runState != RUNNING) {
                  reject(command);
                  return;
              }
              if (poolSize < corePoolSize && addIfUnderCorePoolSize(command))
                  return;
              if (workQueue.offer(command))
                  return;
              int status = addIfUnderMaximumPoolSize(command);
              if (status > 0)      // created new thread
                  return;
              if (status == 0) {   // failed to create thread
                  reject(command);
                  return;
              }
              // Retry if created a new thread but it is busy with another task
          }
      }
public class CustomBlockingQueue<E> extends LinkedBlockingQueue<E> 
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public CustomBlockingQueue() {
    super(Integer.MAX_VALUE);
    }

    public boolean offer(E e) {
       return false;
    }

}
   final CustomThreadPoolExecutor tpe = new CustomThreadPoolExecutor(3, 8, 0L, TimeUnit.MILLISECONDS, new MediationBlockingQueue<Runnable>(), new MediationRejectionHandler());

private static final int TASK_COUNT = 100;

 for (int i = 0; i < TASK_COUNT; i++) {

......
tpe.execute(new Task(i));
.....
}

我们调用的执行器的核心池大小为3,最大池大小为8,并对任务使用无界链接阻塞队列。

共有1个答案

桑飞语
2023-03-14

使用SynchronousQueue实现“在排队前开始但首选现有线程”行为的最简单方法。当且仅当已经有一个等待接收者时,它将接受提供的项目。因此,空闲线程将获得项目,一旦没有空闲线程,ThreadPoolExecutor将启动新的线程。

唯一的缺点是,一旦启动了所有线程,就不能简单地将挂起的项放入队列,因为它没有容量。因此,您要么接受提交器被阻塞,要么需要另一个队列将挂起的任务放入它,另一个后台线程将这些挂起的项目放入同步队列。这个额外的线程不会损害性能,因为它大部分时间都被阻塞在这两个队列中的任何一个中。

class QueuingRejectionHandler implements RejectedExecutionHandler {

  final ExecutorService processPending=Executors.newSingleThreadExecutor();

  public void rejectedExecution(
      final Runnable r, final ThreadPoolExecutor executor) {
    processPending.execute(new Runnable() {
      public void run() {
        executor.execute(r);
      }
    });
  }
}

ThreadPoolExecutor e=new ThreadPoolExecutor(
  corePoolSize, maximumPoolSize, keepAliveTime, unit,
  new SynchronousQueue<Runnable>(), new QueuingRejectionHandler());
 类似资料:
  • 我有一个场景,我必须调用具有相同基本URL的API,例如,但具有不同的。 我有一个Retrofit 2的实例,它是通过构建的: 如下所示: 对于某些,我必须调用相同的API,但在其他情况下,我必须从完全不同的调用它。如何更改实例以因此在运行时指向不同的URL? 改装实例没有

  • 我正在寻找一种通过改变散列来改变部分样式的方法。让我以一个例子来解释: > 当前URL为: 然后单击复选框,URL将更改为: 我想更改类的。 我尝试了以下代码,但它不起作用: 实际上,每次哈希更改时,控制台中都不会出现任何内容。

  • 问题内容: 我们需要将某些列的数据类型从int更改为bigint。不幸的是,其中一些表很大,大约有7-10百万行(但不宽)。 Alter表alter列将永远保留在这些表上。有没有更快的方法来实现这一目标? 问题答案: 巧合的是,大约3个小时前,我不得不做一些非常相似的事情。该表是3500万行,它相当宽,并且花了很多时间才能做到这一点: 这就是我最终得到的结果: 这次,这些陈述几乎是即时的。(在速度

  • 问题内容: 尝试更改列的数据类型并设置新的默认值时遇到以下错误: 错误1064(42000):您的SQL语法有错误;检查与您的MySQL服务器版本相对应的手册,以在第1行的’VARCHAR(255)NOT NULL SET DEFAULT’{}’‘附近使用正确的语法 问题答案: 同样的第二种可能性(感谢juergen_d):

  • 在尝试更改列的数据类型并设置新的默认值时,我遇到以下错误: 错误1064(42000):您的SQL语法中有错误;查看与您的MySQL server版本相对应的手册,以了解第1行“varchar(255)NOT NULL SET DEFAULT”{}“附近使用的正确语法

  • 问题内容: 我知道,我们不能使用来重命名列,但是可以。 我的问题是:的主要用途是什么? 例如, 代替 已编辑的 问题已替换 的主要用途是什么? 上面的问题被下面的问题取代 为什么我们必须使用更改列而不是修改列? 问题答案: CHANGE COLUMN如果您已经创建了MySQL数据库,并确定其中一个列的名称不正确,则无需删除它并进行替换,您只需使用 change column 重命名即可。 MODI

  • 目前,我在改装方面面临一些问题。对于第二个请求,我提供给ReformInstance的URL正在更改。以下是代码: 以下是针对不同API请求的接口方法: UrlEndPoints.kt 对于第一个请求(loginUserByFacebook),我通过调试响应获得的URL是: http://test.sample.com/req/v1/user/auth/facebook 这很好,工作也很好。但是对

  • 问题内容: 我只是在VM上设置了debian 8.3,并在本教程之后安装了xampp 。一切正常,直到我尝试创建一个新表: 我得到了错误: 然后我发现它来自,它仅限于767Byte,可以通过在my.cnf文件中设置innodb_large_prefix来解决此问题。但是我找不到文件,它不在下面,也没有-folder,但是我发现的唯一是在中,但是,我将其添加到文件并重新启动了lampp之后。我仍然得