账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    Java线程池ThreadPoolExecutor中workers.remove(w)疑惑
    32
    0

    在查看Java线程池实现的源码时,对于线程池内部worker生命周期有一个不解的地方:当worker所持有的task,或者线程队列中的task都被执行完以后,为什么worker要被移除线程池的worker集合。

    追踪源码的过程大致是:
    查看execute(Runnable command)方法,发现了addWorker(command, true)的调用

            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);

    进入addWorker(Runnable firstTask, boolean core),发现了worker线程的启动

    if (workerAdded) {
        t.start();
        workerStarted = true;
    }

    Worker类的run方法即调用ThreadPoolExecutor中的runWorker方法。
    在runWorker方法的最后调用了processWorkerExit方法。

    } finally {
        processWorkerExit(w, completedAbruptly);
    }

    在processWorkerExit中发现:

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                completedTaskCount += w.completedTasks;
                workers.remove(w);
            } finally {
                mainLock.unlock();
            }

    worker被从线程集合workers移除了。

    所以疑惑或者问题是:
    线程持中其实是不保有一定数量可用线程,如果当task队列里面没有要处理的任务,原先创造的worker工作线程都会逐步被移除,直到下次再有新的task到来,才又会创建新的worker工作线程??

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 終究是終局ジ 普通会员 1楼

      在Java的ThreadPoolExecutor中,remove()方法用于删除指定线程。这个方法会从线程池中删除指定的线程,并返回这个线程的ID。在使用这个方法时,你应该确保你没有将这个线程ID作为参数传入。

      以下是一个简单的例子,展示了如何使用remove()方法:

      ```java ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());

      // 创建一个新的线程 Runnable task = new Runnable() { @Override public void run() { System.out.println("Task running"); } };

      executor.execute(task);

      // 删除任务 executor.remove(task);

      // 现在任务已经被删除 System.out.println("Task finished"); ```

      在这个例子中,我们首先创建了一个新的线程池,并将一个任务放入了线程池中。然后,我们调用execute()方法来运行这个任务。最后,我们调用remove()方法来删除任务。

      在调用remove()方法时,你应该确保你没有将任务ID作为参数传入。这是因为这个方法会从线程池中删除指定的线程,而不是返回这个线程ID。如果你需要返回线程ID,你应该在调用remove()方法之前,将这个线程ID作为参数传入。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部