Commonly used method

As we know in the previous section, the final execution of the task is related to the Worker class, and the number of workers in the thread pool represents the number of threads.

Submit (Callable

task), submit(Runnable task) : The task is encapsulated as a FutureTask object, which is an implementation class of RunnableFuture with member variables such as status and result. If it is a Callable implementation class, the Call () method is called, and if it is a Runnable implementation class, the run() method is called. Get () will block until the result is produced, or null for return type void

invokeAll(Collection
> Tasks) : Tasks are a collection of implementation classes for the Callable interface that perform implementation-class tasks and block until all tasks are complete

Shutdown () : Sets the thread pool state to shutdown, stops receiving new tasks, and then tries to interrupt Worker threads waiting for blocked queue tasks

ThreadPoolExecutor->interruptIdleWorkers(): for (Worker w : workers) { Thread t = w.thread; // W is the worker class, tryLock() will only succeed if the state is 0. t.isInterrupted() && w.tryLock()) { try { t.interrupt(); .Copy the code

ShutdownNow () : Sets the thread pool state to STOP, and then stops the Worker thread in the thread pool (whether completed or not), returning to block the task in the queue

ThreadPoolExecutor->interruptWorkers():
    for (Worker w : workers)
        w.interruptIfStarted();
Copy the code

GetPoolSize () : Returns the number of Worker threads in the thread pool

GetActiveCount () : Returns the number of Worker threads executing tasks in the thread pool

GetCompletedTaskCount () : Returns the number of tasks completed by the thread pool, and the completedTaskCount is added to each Worker thread

PrestartCoreThread () : Adds a core worker thread

PrestartAllCoreThreads () : Adds core worker threads until the number of corePoolSize is reached

SetCorePoolSize (int corePoolSize) : Set the number of core threads to corePoolSize. If the number of Worker threads is greater than the number of core threads, try to interrupt the Worker thread waiting for the blocking queue task. If you increase the number of core threads, try adding Worker threads to the tasks in the blocking queue

SetMaximumPoolSize (int maximumPoolSize) : Set the maximum number of threads to maximumPoolSize. If the number of Worker threads is greater than the maximum number of threads, try to interrupt the Worker thread waiting for the blocking queue task

SetKeepAliveTime (long time, TimeUnit Unit) : Reset keepAliveTime+unit and try to interrupt Worker threads waiting for blocking queue tasks if the interval is set too small

Special thread pool

Singleton thread pool

SingleThreadExecutor() a corePoolSize that goes beyond the entire block queue into the LinkedBlockingQueue

Fixed thread pool

FixedThreadExecutor(n) : n corePoolsizes, all of which are added to the LinkedBlockingQueue blocking queue

Cache thread pool

CachedThreadPool: 0 corePoolSize, the blocking queue SynchronousQueue does not receive the task, integer. MAX_VALUE is maximumPoolSize, and the Worker exits if no task is received in 60 seconds

Timed thread pool

ScheduledThreadPool(n) : n corePoolSizes that first place the task in the DelayedWorkQueue blocking queue and then start the core thread. Return ScheduledThreadPoolExecutor object.

ScheduleAtFixedRate (Runnable Command,long initialDelay,long period,TimeUnit unit) : Assume that unit is second, initialDelay is 2, and period is 3, then start after 2s delay, and execute the next task immediately after 3s if the task is completed, otherwise execute the next one after the task is completed. Returns the ScheduledFutureTask object.

ScheduleWithFixedDelay (Runnable Command,long initialDelay,long delay,TimeUnit unit) : Assume that unit is second, initialDelay is 2, period is 3, then start after 2s delay, and execute the next task after 3s. Returns the ScheduledFutureTask object.

ScheduledThreadPoolExecutor->execute(): schedule(command, 0, NANOSECONDS); ScheduledThreadPoolExecutor->schedule(): RunnableScheduledFuture<? > t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); // Add the task to the blocking queue. If the number of worker threads is smaller than the number of core threads, start a worker thread delayedExecute(t);Copy the code
ScheduledThreadPoolExecutor->scheduleAtFixedRate():
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      unit.toNanos(period));
Copy the code
ScheduledThreadPoolExecutor->scheduleWithFixedDelay():
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      unit.toNanos(-delay));
Copy the code

TriggerTime (delay, unit), calculates the nanosecond time to execute the task, if 0, the current nanosecond time; If delay is 3 and unit is second, it is the current time +3s nanoseconds.

ScheduledThreadPoolExecutor->ScheduledFutureTask->ScheduledFutureTask(Runnable r, V result, long ns, long period): super(r, result); // This. Time = ns; // this. Period = period; this.sequenceNumber = sequencer.getAndIncrement();Copy the code

Notice that the three methods specify different time periods, where execute() is 0, scheduleAtFixedRate() is a positive number, and scheduleWithFixedDelay() is a negative number.

DelayedWorkQueue Overrides a common method for blocking queues, such as take()

ScheduledThreadPoolExecutor->DelayedWorkQueue->take(): RunnableScheduledFuture<? > first = queue[0]; If (first == null) // if there is no task, block all the time // Add () calls available.signal(), which wakes up available.await(); Else {// Long delay = first.getdelay (NANOSECONDS); If (delay <= 0) return finishPoll(first); if (delay <= 0) return finishPoll(first); first = null; . // Otherwise, if there is a difference of one second, let the thread sleep for one second and try available.awaitnanos (delay);Copy the code

After the task is completed, the next execution time is calculated according to different methods.

ScheduledThreadPoolExecutor - > ScheduledFutureTask - > run () : / / cycle is equal to 0 Boolean periodic = isPeriodic (); if (! canRunInCurrentRunState(periodic)) cancel(false); // If = 0, else if (! periodic) ScheduledFutureTask.super.run(); / / perform a task, if the task status is not 0 else if return false (ScheduledFutureTask. Super. RunAndReset ()) {/ / set the time of the next mission setNextRunTime (); ReExecutePeriodic (outerTask); } ScheduledThreadPoolExecutor->ScheduledFutureTask->setNextRunTime(): // --1 long p = period; If (p > 0) // scheduleAtFixedRate() time = p; ScheduleWithFixedDelay () time = triggerTime(-p);Copy the code

Scheduledfuture. cancel(Boolean mayInterruptIfRunning) : Cancels the task or interrupts the thread if mayInterruptIfRunning is true. The principle is to change the task status. If the task status is not 0, the steps of executing the task and calculating the execution time of the next task are skipped.

Application: SpringBoot timing task annotation @enablesCheduling implementation