【问题标题】:ThreadPoolExecutor Java线程池执行器 Java
【发布时间】:2017-12-29 16:03:50
【问题描述】:

我有一个示例代码。

@Test
    public void testWithBlockQueue() throws InterruptedException {
        String poolFormat = "ServiceTaskPool-%d";
        int coreSize = 3;
        int maxSize = 3;
        int queueSize = 1;
        int idleThreadLiveInSecond = 35;

        ThreadFactory factory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r);
            }
        };
        ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(queueSize);
        final ThreadPoolExecutor service = new ThreadPoolExecutor(coreSize, maxSize, idleThreadLiveInSecond,
                TimeUnit.SECONDS, queue, factory, new ThreadPoolExecutor.AbortPolicy());
        service.allowCoreThreadTimeOut(true);
        passTask(coreSize, service);
        Thread.sleep(5000);
        passTask(coreSize, service);
        System.out.printf("Thread pool state %s", service);
        Thread.sleep(6000);
    }

    protected void passTask(int coreSize, ThreadPoolExecutor service) {
        for (int i=0; i < coreSize; i++) {
            service.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.printf("Simple printf from %s \n", Thread.currentThread().getName());
                }
            });
        }
    }

当我设置 queueSize 2 时,我得到了异常,因为当我设置 queueSize 3 时,threadpoolexecutor 无法将一项任务插入队列。我不明白为什么当我设置 maxSize = 4 时,测试没问题。 它来自文档。

  1. 如果线程数小于corePoolSize,新建一个 线程运行新任务。
  2. 如果线程数等于(或大于) corePoolSize,将任务放入队列。
  3. 如果队列已满,并且线程数小于 maxPoolSize,创建一个新线程来运行任务。
  4. 如果队列已满,并且线程数大于或 等于 maxPoolSize,拒绝任务。

【问题讨论】:

    标签: java java.util.concurrent threadpoolexecutor


    【解决方案1】:

    其实当maxSize = 4时,可能会抛出异常

    第一次调用passTask(coreSize, service),我们得到task1,task2,task3。并且会创建thread1、thread2、thread3来运行它们。

    第二次致电passTask(coreSize, service):

    1. i = 0,我们得到task4,task4会被放入队列中。
    2. i = 1,我们得到 task5。

      2.1。如果 task4 还在队列中,则创建 thread4 并运行 task5;

      2.2。如果task4已经被thread1或thread2或thread3从队列中取出,task5将被放入队列中。

    3. i = 2,获得 task6。

      3.1。如果task4还在队列中,肯定有4个存活线程,并且因为队列满了,会抛出异常;

      3.2。如果task5在队列中,肯定有3个线程活着,所以会创建thread4并运行task6;

      3.3。如果队列为空,task6将被放入队列中。

    在条件 3.1 上,可能会引发异常。但是在测试中,任务会非常快地从块队列中取出,所以这种情况几乎不会发生。

    附注:

    当 maxSize = 3 且 queueSize = 1 时,添加这一行

    Thread.sleep(10);

    之后

    for (int i=0; i &lt; coreSize; i++) {

    可以让你的代码无异常运行。

    【讨论】:

      猜你喜欢
      • 2014-08-27
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      • 2019-02-19
      • 1970-01-01
      • 2018-07-28
      • 2022-01-18
      相关资源
      最近更新 更多