ThreadPoolExecutor.execute (команда Runnable) когда создавать новый поток - PullRequest
1 голос
/ 13 июня 2019

Я читаю исходный код ThreadPoolExecutor.java для метода execute, описанного ниже:

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        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);
    }

Предположим, что в пуле потоков есть 2 основных потока, а максимальный размер пула равен 4.

Я могу понять код if (workerCountOf(c) < corePoolSize) { addWorkder(..) }, это означает, что если в настоящее время число основных потоков меньше, чем размер опроса ядра, просто создайте новый поток для обработки команды runnable.

Что я не могу понять, так этоСкажем, если мы уже два раза звонили execute(runnable), и каждому из них требуется много времени для завершения, поэтому они все еще заняты, и теперь мы звоним в третий раз.

Что будет делать код?Я думаю, что код идет к if (isRunning(c) && workQueue.offer(command)) {, поэтому команда добавляется в рабочую очередь.Однако я не понимаю, какая третья команда будет выполняться каким потоком.Согласно коду else if (workerCountOf(recheck) == 0), я думаю, что количество рабочих должно быть 2, потому что мы уже добавили двух рабочих.

Поэтому мой вопрос, когда будет добавлен 3-й рабочий?

- Правка-

Мой код тестирования:


public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,
                4,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4)
        );

        threadPoolExecutor.execute(new Command("A"));
        threadPoolExecutor.execute(new Command("B"));
        threadPoolExecutor.execute(new Command("C"));

    }

    static class Command implements Runnable {
        private String task;
        Command(String task) {
            this.task = task;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000 * 10);
                System.out.println(new Date() + " - " + Thread.currentThread().getName() + " : " + task);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Он печатает:

Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-1 : A
Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-2 : B
Thu Jun 13 17:44:40 CST 2019 - pool-1-thread-1 : C

С кодом тестирования я ожидаю, что основные работники будут заняты в течение 10 секунд, поэтомукогда execute("C") я хочу обратить внимание на случай «основные работники заняты, и третий работник будет добавлен», но кажется, что третьего работника нет?Извините, но что не так?

Спасибо.

1 Ответ

2 голосов
/ 13 июня 2019

Я хочу поразмыслить: «Основные работники заняты, и третий сотрудник будет добавлен»

Тогда вы также должны заполнить очередь.

Джавадок говорит:

Когда новая задача отправляется в метод execute (java.lang.Runnable) и выполняется меньше потоков corePoolSize, создается новый поток для обработки запроса, даже если другие рабочие потоки простаивают. Если запущено больше чем corePoolSize, но меньше чем MaximumPoolSize потоков, новый поток будет создан, только если очередь заполнена .

...