Summary 1.

ScheduledThreadPoolExecutor inheritance ThreadPoolExecutor to rewrite the execute and submit,

It also implements ScheduledExecutorService specific methods.

Its main purpose is toImplement periodic task execution or asynchronous task execution after a given time.

There are also two important inner classes in this class

  1. DelayWorkQueue

    The main implementation of blocking queue interface, it can be seen that it is a customized blocking queue,

  1. ScheduledFutureTask

    ScheduledFutureTask has all the functionality of the FutureTask class and implements all the methods of the RunnableScheduledFuture interface.

    The ScheduledFutureTask class is defined as follows

2. Construction method

// The maximum number of threads is integer.max_value, In theory is an infinity of thread pool public ScheduledThreadPoolExecutor (int corePoolSize) {super (corePoolSize, Integer. MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); } public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory); } public ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), handler); } public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler); }Copy the code

3. Unique methods

// Creates and performs an action that is enabled after the given delay. public ScheduledFuture<? > schedule(Runnable command, long delay, TimeUnit unit); Public <V> ScheduledFuture<V> schedule(Callable<V> Callable, long delay, TimeUnit unit); Public ScheduledFuture<? Public ScheduledFuture<? > scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); Public ScheduledFuture<? > scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);Copy the code

Practice of 4.

No practice, no theory

public static void schedule(ScheduledExecutorService executorService){ executorService.schedule(() ->{ for (int i= 0 ; i <10 ; i++) { executorService.submit(() -> { System.out.println("CurrentThread name:" + Thread.currentThread().getName() + "Date:" + Instant. Now ()); }); } },5, TimeUnit.SECONDS); } public static void scheduleCall(ScheduledExecutorService executorService){ ScheduledFuture scheduledFuture = executorService.schedule(() -> "scheduleCall",1L,TimeUnit.SECONDS); try { System.out.println(scheduledFuture.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } public static void scheduleAtFixedRate(ScheduledExecutorService executorService) { ScheduledFuture scheduledFuture =  executorService.scheduleAtFixedRate(() -> { for (int i = 0; i < 10; i++) { executorService.submit(() -> { System.out.println("CurrentThread name:" + Thread.currentThread().getName() + "Date:" + Instant. Now ()); }); } } , 0, 5L, TimeUnit.SECONDS); try { System.out.println(scheduledFuture.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }} // For exceptions, Public static void scheduleWithFixedDelay(ScheduledExecutorService executorService) {ScheduledFuture scheduledFuture = executorService.scheduleWithFixedDelay(() -> { try { int j = 1 / 0; } catch (Exception e) { e.printStackTrace(); } } , 10, 5L, TimeUnit.SECONDS); }Copy the code

5. Source code

Parameter description: command: indicates the task to be executed. Delay: indicates the delay time. Unit: indicates the time unit

public ScheduledFuture<? > schedule(Runnable command, long delay, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); // Convert the submitted task to ScheduledFutureTask, or periodic task if period is true RunnableScheduledFuture<? > t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); // The main execution method of the task is delayedExecute(t); return t; }Copy the code

ScheduledThreadPoolExecutor mainly is delay or periodic tasks, the completion of delayedExecute method is mainly the implementation of the final through ensurePrestart method, add the thread startup tasks.

private void delayedExecute(RunnableScheduledFuture<? > task) {if (isShutdown()) // Call the reject policy (task) if the thread pool has stopped; Else {// Add the task to the Worker blocking queue super.getQueue().add(task); if (isShutdown() && ! CanRunInCurrentRunState (task.isPeriodic()) && Remove (task)) // Cancel and delete task task.cancel(false); Else start at least one thread to execute ensurePrestart(); }}Copy the code
Void ensurePrestart() {int wc = workerCountOf(ctl.get()); if (wc < corePoolSize) addWorker(null, true); else if (wc == 0) addWorker(null, false); }Copy the code

Seeing the familiar addWorker method again, we can look through the previous article to see the main execution process. The main flow of addWorker:

  1. Check thread pool status
  2. Create a new thread, wrap it with the Worker, and put it into the Hashet array. Finally, the thread that actually performs the task is placed in the Worker, so adding an addWorker means adding a new thread. The main implementation of reuse is runWorker(this) in the Worker class.
  3. Start thread Start()
  4. Add failed operations, remove workers, and reduce WorkerCount

6. Summary

Conclusion:

Three main objects

Performer: Worker

Task: ScheduledFutureTask

Result: ScheduledFuture

Process:

  1. Convert the submitted task to ScheduledFutureTask
  2. Add the ScheduledFutureTask to the Worker queue
  3. Call the addWorker method and call its core method runWorker
  4. The getTask method is called to retrieve tasks from the blocking queue until the task is null and the thread terminates