1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.concurrency.ScheduledExecutorService; 13 14 import hunt.concurrency.ExecutorService; 15 import hunt.concurrency.Delayed; 16 17 import hunt.util.Common; 18 import hunt.util.Runnable; 19 20 import core.time; 21 22 /** 23 * An {@link ExecutorService} that can schedule commands to run after a given 24 * delay, or to execute periodically. 25 * 26 * <p>The {@code schedule} methods create tasks with various delays 27 * and return a task object that can be used to cancel or check 28 * execution. The {@code scheduleAtFixedRate} and 29 * {@code scheduleWithFixedDelay} methods create and execute tasks 30 * that run periodically until cancelled. 31 * 32 * <p>Commands submitted using the {@link Executor#execute(Runnable)} 33 * and {@link ExecutorService} {@code submit} methods are scheduled 34 * with a requested delay of zero. Zero and negative delays (but not 35 * periods) are also allowed in {@code schedule} methods, and are 36 * treated as requests for immediate execution. 37 * 38 * <p>All {@code schedule} methods accept <em>relative</em> delays and 39 * periods as arguments, not absolute times or dates. It is a simple 40 * matter to transform an absolute time represented as a {@link 41 * java.util.Date} to the required form. For example, to schedule at 42 * a certain future {@code date}, you can use: {@code schedule(task, 43 * date.getTime() - System.currentTimeMillis(), 44 * TimeUnit.MILLISECONDS)}. Beware however that expiration of a 45 * relative delay need not coincide with the current {@code Date} at 46 * which the task is enabled due to network time synchronization 47 * protocols, clock drift, or other factors. 48 * 49 * <p>The {@link Executors} class provides convenient factory methods for 50 * the ScheduledExecutorService implementations provided in this package. 51 * 52 * <h3>Usage Example</h3> 53 * 54 * Here is a class with a method that sets up a ScheduledExecutorService 55 * to beep every ten seconds for an hour: 56 * 57 * <pre> {@code 58 * import static hunt.concurrency.TimeUnit.*; 59 * class BeeperControl { 60 * private final ScheduledExecutorService scheduler = 61 * Executors.newScheduledThreadPool(1); 62 * 63 * public void beepForAnHour() { 64 * Runnable beeper = () -> System.out.println("beep"); 65 * ScheduledFuture<?> beeperHandle = 66 * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); 67 * Runnable canceller = () -> beeperHandle.cancel(false); 68 * scheduler.schedule(canceller, 1, HOURS); 69 * } 70 * }}</pre> 71 * 72 * @author Doug Lea 73 */ 74 interface ScheduledExecutorService : ExecutorService { 75 76 /** 77 * Submits a one-shot task that becomes enabled after the given delay. 78 * 79 * @param command the task to execute 80 * @param delay the time from now to delay execution 81 * @param unit the time unit of the delay parameter 82 * @return a ScheduledFuture representing pending completion of 83 * the task and whose {@code get()} method will return 84 * {@code null} upon completion 85 * @throws RejectedExecutionException if the task cannot be 86 * scheduled for execution 87 * @throws NullPointerException if command or unit is null 88 */ 89 ScheduledFuture!void schedule(Runnable command, Duration delay); 90 91 // /** 92 // * Submits a value-returning one-shot task that becomes enabled 93 // * after the given delay. 94 // * 95 // * @param callable the function to execute 96 // * @param delay the time from now to delay execution 97 // * @param unit the time unit of the delay parameter 98 // * @param (V) the type of the callable's result 99 // * @return a ScheduledFuture that can be used to extract result or cancel 100 // * @throws RejectedExecutionException if the task cannot be 101 // * scheduled for execution 102 // * @throws NullPointerException if callable or unit is null 103 // */ 104 // !(V) ScheduledFuture!(V) schedule(Callable!(V) callable, Duration delay); 105 106 /** 107 * Submits a periodic action that becomes enabled first after the 108 * given initial delay, and subsequently with the given period; 109 * that is, executions will commence after 110 * {@code initialDelay}, then {@code initialDelay + period}, then 111 * {@code initialDelay + 2 * period}, and so on. 112 * 113 * <p>The sequence of task executions continues indefinitely until 114 * one of the following exceptional completions occur: 115 * <ul> 116 * <li>The task is {@linkplain Future#cancel explicitly cancelled} 117 * via the returned future. 118 * <li>The executor terminates, also resulting in task cancellation. 119 * <li>An execution of the task throws an exception. In this case 120 * calling {@link Future#get() get} on the returned future will throw 121 * {@link ExecutionException}, holding the exception as its cause. 122 * </ul> 123 * Subsequent executions are suppressed. Subsequent calls to 124 * {@link Future#isDone isDone()} on the returned future will 125 * return {@code true}. 126 * 127 * <p>If any execution of this task takes longer than its period, then 128 * subsequent executions may start late, but will not concurrently 129 * execute. 130 * 131 * @param command the task to execute 132 * @param initialDelay the time to delay first execution 133 * @param period the period between successive executions 134 * @param unit the time unit of the initialDelay and period parameters 135 * @return a ScheduledFuture representing pending completion of 136 * the series of repeated tasks. The future's {@link 137 * Future#get() get()} method will never return normally, 138 * and will throw an exception upon task cancellation or 139 * abnormal termination of a task execution. 140 * @throws RejectedExecutionException if the task cannot be 141 * scheduled for execution 142 * @throws NullPointerException if command or unit is null 143 * @throws IllegalArgumentException if period less than or equal to zero 144 */ 145 ScheduledFuture!void scheduleAtFixedRate(Runnable command, 146 Duration initialDelay, 147 Duration period); 148 149 /** 150 * Submits a periodic action that becomes enabled first after the 151 * given initial delay, and subsequently with the given delay 152 * between the termination of one execution and the commencement of 153 * the next. 154 * 155 * <p>The sequence of task executions continues indefinitely until 156 * one of the following exceptional completions occur: 157 * <ul> 158 * <li>The task is {@linkplain Future#cancel explicitly cancelled} 159 * via the returned future. 160 * <li>The executor terminates, also resulting in task cancellation. 161 * <li>An execution of the task throws an exception. In this case 162 * calling {@link Future#get() get} on the returned future will throw 163 * {@link ExecutionException}, holding the exception as its cause. 164 * </ul> 165 * Subsequent executions are suppressed. Subsequent calls to 166 * {@link Future#isDone isDone()} on the returned future will 167 * return {@code true}. 168 * 169 * @param command the task to execute 170 * @param initialDelay the time to delay first execution 171 * @param delay the delay between the termination of one 172 * execution and the commencement of the next 173 * @param unit the time unit of the initialDelay and delay parameters 174 * @return a ScheduledFuture representing pending completion of 175 * the series of repeated tasks. The future's {@link 176 * Future#get() get()} method will never return normally, 177 * and will throw an exception upon task cancellation or 178 * abnormal termination of a task execution. 179 * @throws RejectedExecutionException if the task cannot be 180 * scheduled for execution 181 * @throws NullPointerException if command or unit is null 182 * @throws IllegalArgumentException if delay less than or equal to zero 183 */ 184 ScheduledFuture!void scheduleWithFixedDelay(Runnable command, 185 Duration initialDelay, 186 Duration delay); 187 188 }